{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Title: #Lowest Common Ancestor of a Binary Tree IV"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Difficulty: #Medium"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Category Title: #Algorithms"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Tag Slug: #tree #depth-first-search #hash-table #binary-tree"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Name Translated: #树 #深度优先搜索 #哈希表 #二叉树"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Solution Name: lowestCommonAncestor"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Translated Title: #二叉树的最近公共祖先 IV"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Translated Content:\n",
    "<p>给定一棵二叉树的根节点 <code>root</code> 和 <code>TreeNode</code> 类对象的数组（列表） <code>nodes</code>，返回<em> </em><code>nodes</code> 中所有节点的最近公共祖先（LCA）。数组（列表）中所有节点都存在于该二叉树中，且二叉树中所有节点的值都是互不相同的。</p>\n",
    "\n",
    "<p>我们扩展<a href=\"https://en.wikipedia.org/wiki/Lowest_common_ancestor\" target=\"_blank\">二叉树的最近公共祖先节点在维基百科上的定义</a>：“对于任意合理的 <code>i</code> 值， <code>n</code> 个节点 <code>p<sub>1</sub></code> 、 <code>p<sub>2</sub></code>、...、 <code>p<sub>n</sub></code> 在二叉树 <code>T</code> 中的最近公共祖先节点是<strong>后代</strong>中包含所有节点 <code>p<sub>i</sub></code> 的最深节点（我们允许一个节点是其自身的后代）”。一个节点 <code>x</code> 的后代节点是节点 <code>x</code> 到某一叶节点间的路径中的节点 <code>y</code>。</p>\n",
    "\n",
    "<p> </p>\n",
    "\n",
    "<p><strong>示例 1:</strong></p>\n",
    "<img alt=\"\" src=\"https://assets.leetcode.com/uploads/2018/12/14/binarytree.png\">\n",
    "<pre><strong>输入:</strong> root = [3,5,1,6,2,0,8,null,null,7,4], nodes = [4,7]\n",
    "<strong>输出:</strong> 2\n",
    "<strong>解释:</strong> 节点 4 和 7 的最近公共祖先是 2。\n",
    "</pre>\n",
    "\n",
    "<p><strong>示例 2:</strong></p>\n",
    "<img alt=\"\" src=\"https://assets.leetcode.com/uploads/2018/12/14/binarytree.png\">\n",
    "<pre><strong>输入:</strong> root = [3,5,1,6,2,0,8,null,null,7,4], nodes = [1]\n",
    "<strong>输出:</strong> 1\n",
    "<strong>解释:</strong> 单个节点的最近公共祖先是该节点本身。\n",
    "\n",
    "</pre>\n",
    "\n",
    "<p><strong>示例 3:</strong></p>\n",
    "<img alt=\"\" src=\"https://assets.leetcode.com/uploads/2018/12/14/binarytree.png\">\n",
    "<pre><strong>输入:</strong> root = [3,5,1,6,2,0,8,null,null,7,4], nodes = [7,6,2,4]\n",
    "<strong>输出:</strong> 5\n",
    "<strong>解释:</strong> 节点 7、6、2 和 4 的最近公共祖先节点是 5。\n",
    "</pre>\n",
    "\n",
    "<p><strong>示例 4:</strong></p>\n",
    "<img alt=\"\" src=\"https://assets.leetcode.com/uploads/2018/12/14/binarytree.png\">\n",
    "<pre><strong>输入:</strong> root = [3,5,1,6,2,0,8,null,null,7,4], nodes = [0,1,2,3,4,5,6,7,8]\n",
    "<strong>输出:</strong> 3\n",
    "<strong>解释:</strong> 树中所有节点的最近公共祖先是根节点。\n",
    "</pre>\n",
    "\n",
    "<p> </p>\n",
    "\n",
    "<p><strong>提示:</strong></p>\n",
    "\n",
    "<ul>\n",
    "\t<li>树中节点个数的范围是 <code>[1, 10<sup>4</sup>]</code> 。</li>\n",
    "\t<li><code>-10<sup>9</sup> &lt;= Node.val &lt;= 10<sup>9</sup></code></li>\n",
    "\t<li>所有的 <code>Node.val</code> 都是<strong>互不相同</strong>的。</li>\n",
    "\t<li>所有的 <code>nodes[i]</code> 都存在于该树中。</li>\n",
    "\t<li>所有的 <code>nodes[i]</code> 都是互不相同的。</li>\n",
    "</ul>\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Description: [lowest-common-ancestor-of-a-binary-tree-iv](https://leetcode.cn/problems/lowest-common-ancestor-of-a-binary-tree-iv/description/)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Solutions: [lowest-common-ancestor-of-a-binary-tree-iv](https://leetcode.cn/problems/lowest-common-ancestor-of-a-binary-tree-iv/solutions/)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "test_cases = ['[3,5,1,6,2,0,8,null,null,7,4]\\n[4,7]', '[3,5,1,6,2,0,8,null,null,7,4]\\n[1]', '[3,5,1,6,2,0,8,null,null,7,4]\\n[7,6,2,4]']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':\n",
    "      depths, nodes = [], []\n",
    "      idx = {}\n",
    "      \n",
    "      def visit(root, depth):\n",
    "        if not root:\n",
    "          return\n",
    "        nonlocal depths, nodes, idx\n",
    "        visit(root.left, depth+1)\n",
    "        depths.append(depth)\n",
    "        idx[root] = len(nodes)\n",
    "        nodes.append(root)\n",
    "        visit(root.right, depth + 1)\n",
    "      \n",
    "      visit(root, 0)\n",
    "      idxP, idxQ = idx.get(p, -1), idx.get(q, -1)\n",
    "      if idxP < 0 or idxQ < 0:\n",
    "        return None\n",
    "      \n",
    "      minIdx, maxIdx = min(idxP, idxQ), max(idxP, idxQ)\n",
    "      parentIdx, parentDepth = minIdx, depths[minIdx]\n",
    "      for i in range(minIdx, maxIdx+1):\n",
    "        if depths[i] < parentDepth:\n",
    "          parentDepth = depths[i]\n",
    "          parentIdx = i\n",
    "      return nodes[parentIdx]\n",
    "              \n",
    "\n",
    "    def lowestCommonAncestor1(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':\n",
    "        pFound, qFound = False, False\n",
    "        \n",
    "        def check(root):\n",
    "          nonlocal pFound, qFound\n",
    "          if not root:\n",
    "            return\n",
    "          if root.val == p.val:\n",
    "            pFound = True\n",
    "          if root.val == q.val:\n",
    "            qFound = True\n",
    "          if not pFound or not qFound:\n",
    "            check(root.left)\n",
    "            check(root.right)\n",
    "            \n",
    "        def helper(root, p, q):\n",
    "          if not root:\n",
    "            return None\n",
    "          \n",
    "          if root.val == p.val or root.val == q.val:\n",
    "            return root\n",
    "          left = helper(root.left, p, q)\n",
    "          right = helper(root.right, p, q)\n",
    "          if left and right:\n",
    "            return root\n",
    "          return left if left else right        \n",
    "\n",
    "        check(root)\n",
    "        if not pFound or not qFound:\n",
    "          return None\n",
    "        return helper(root, p, q)        \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':\n",
    "        def dfs(root):\n",
    "            stack = [root]\n",
    "            visited = set()\n",
    "            ress = []\n",
    "            while(stack):\n",
    "                cur = stack[-1]\n",
    "                if cur is None:\n",
    "                    ress.append(0)\n",
    "                    stack.pop()\n",
    "                    continue\n",
    "                if cur.val in visited:\n",
    "                    tmp = (cur == p or cur == q) + ress.pop() + ress.pop()\n",
    "                    if tmp == 2:\n",
    "                        return cur\n",
    "                    ress.append(tmp)\n",
    "                    stack.pop()\n",
    "                    continue\n",
    "                visited.add(cur.val)\n",
    "                stack.append(cur.left)\n",
    "                stack.append(cur.right)\n",
    "            return None\n",
    "        return dfs(root)\n",
    "        # def dfs(root):\n",
    "        #     stack = [root]\n",
    "        #     path = set()\n",
    "        #     visited = set()\n",
    "        #     meet_p = False\n",
    "        #     meet_q = False\n",
    "        #     while(stack):\n",
    "        #         cur = stack[-1]\n",
    "        #         if cur is None:\n",
    "        #             stack.pop()\n",
    "        #             continue\n",
    "        #         if cur.val in visited:\n",
    "        #             if meet_p and meet_q and cur.val in path:\n",
    "        #                 return cur\n",
    "        #             stack.pop()\n",
    "        #             path.discard(cur.val)\n",
    "        #             continue\n",
    "        #         if not meet_p and not meet_q:\n",
    "        #             path.add(cur.val)\n",
    "        #         visited.add(cur.val)\n",
    "        #         if cur.val == p.val:\n",
    "        #             meet_p = True\n",
    "        #         if cur.val == q.val:\n",
    "        #             meet_q = True\n",
    "        #         stack.append(cur.left)\n",
    "        #         stack.append(cur.right)\n",
    "        #     return None\n",
    "        # return dfs(root)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':\n",
    "        def dfs(root):\n",
    "            stack = [root]\n",
    "            path = set()\n",
    "            visited = set()\n",
    "            meet_p = False\n",
    "            meet_q = False\n",
    "            while(stack):\n",
    "                cur = stack[-1]\n",
    "                if cur is None:\n",
    "                    stack.pop()\n",
    "                    continue\n",
    "                if cur.val in visited:\n",
    "                    if meet_p and meet_q and cur.val in path:\n",
    "                        return cur\n",
    "                    stack.pop()\n",
    "                    path.discard(cur.val)\n",
    "                    continue\n",
    "                if not meet_p and not meet_q:\n",
    "                    path.add(cur.val)\n",
    "                visited.add(cur.val)\n",
    "                if cur.val == p.val:\n",
    "                    meet_p = True\n",
    "                if cur.val == q.val:\n",
    "                    meet_q = True\n",
    "                stack.append(cur.left)\n",
    "                stack.append(cur.right)\n",
    "            return None\n",
    "        return dfs(root)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':\n",
    "\n",
    "        p_path = self.dfs(root, p, [])\n",
    "        \n",
    "\n",
    "        q_path = self.dfs(root, q, [])\n",
    "        \n",
    "       \n",
    "       \n",
    "        if p_path !=None and q_path!= None:\n",
    "           \n",
    "           \n",
    "          \n",
    "\n",
    "            for i in range(min(len(p_path), len(q_path))):\n",
    "\n",
    "                if p_path[i] !=q_path[i]:\n",
    "                    \n",
    "                    return TreeNode(p_path[i-1])\n",
    "            \n",
    "            return TreeNode(p_path[i])\n",
    "            \n",
    "\n",
    "        return TreeNode(\"null\")\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "    \n",
    "    def dfs(self, root, node, path):\n",
    "\n",
    "        if root == None:\n",
    "            path.append(\"none\")\n",
    "            return None\n",
    "        \n",
    "        path.append(root.val)\n",
    "      \n",
    "        \n",
    "        if root.val == node.val:\n",
    "           \n",
    "            return path\n",
    "\n",
    "        left_path = self.dfs(root.left, node, path)\n",
    "        \n",
    "   \n",
    "        if left_path!=None:\n",
    "           \n",
    "            return left_path\n",
    "        else:\n",
    "            path.pop()\n",
    "            right_path = self.dfs(root.right, node, path)\n",
    "            if right_path != None:\n",
    "\n",
    "                return right_path\n",
    "            \n",
    "            else:\n",
    "                path.pop()\n",
    "                return right_path\n",
    "        \n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':\n",
    "        flag_p = flag_q = False\n",
    "        \n",
    "        def dfs(root):\n",
    "            nonlocal flag_p,flag_q\n",
    "            if root == p:\n",
    "                flag_p = True\n",
    "            if root == q:\n",
    "                flag_q = True\n",
    "            if flag_p and flag_q:\n",
    "                return \n",
    "            if root.left:\n",
    "                dfs(root.left)\n",
    "            if root.right:\n",
    "                dfs(root.right)\n",
    "        \n",
    "\n",
    "        def dfs1(root):\n",
    "            if root == None or root == p or root == q:\n",
    "                return root\n",
    "            left = dfs1(root.left)\n",
    "            right = dfs1(root.right)\n",
    "            if left and right:\n",
    "                return root\n",
    "            if not left and not right:\n",
    "                return None\n",
    "            return left if left else right\n",
    "        \n",
    "        dfs(root)\n",
    "        if flag_p and flag_q:\n",
    "            return dfs1(root)\n",
    "        return None"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':\n",
    "        self.hasP, self.hasQ = False, False\n",
    "        def hasNode(root, p, q):\n",
    "            if root:\n",
    "                if root == p:\n",
    "                    self.hasP = True\n",
    "                if root == q:\n",
    "                    self.hasQ = True\n",
    "                hasNode(root.left, p, q)\n",
    "                hasNode(root.right, p, q)\n",
    "            return self.hasP and self.hasQ\n",
    "        hasNode = hasNode(root, p, q)\n",
    "        if not hasNode:\n",
    "            return None\n",
    "        def dfs(node):\n",
    "            if not node:\n",
    "                return None\n",
    "            if node == p or node == q:\n",
    "                return node\n",
    "            left = dfs(node.left)\n",
    "            right = dfs(node.right)\n",
    "            if left and right:\n",
    "                return node\n",
    "            elif left:\n",
    "                return left\n",
    "            elif right:\n",
    "                return right\n",
    "            return None\n",
    "        return dfs(root)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution: #这道题没有保证一定存在p和q因此不能在前序位置碰到就反回了，必须完全遍历整颗树\n",
    "    def __init__(self):\n",
    "        self.p = False\n",
    "        self.q = False\n",
    "\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':\n",
    "        ans = self.BackTrack(root, p, q)\n",
    "        return ans if self.p and self.q else None\n",
    "    \n",
    "    def BackTrack(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode'):\n",
    "        if not root:\n",
    "            return None\n",
    "        left = self.BackTrack(root.left, p, q)\n",
    "        right = self.BackTrack(root.right, p, q)\n",
    "        if left and right: # 不存在重复值因此必定可以返回root - 判断是否是LCA\n",
    "            return root\n",
    "        if root.val == p.val: # 判断是否是p，q中的一员 由于LCA的返回和left，right返回无法区分因此通过全局变量区分\n",
    "            self.p = True\n",
    "            return root\n",
    "        if root.val == q.val: \n",
    "            self.q = True\n",
    "            return root\n",
    "        return left if left else right # 将下面的p或q返回上去\n",
    "        \n",
    "\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def __init__(self):\n",
    "        self.getP = False\n",
    "        self.getQ = False\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':\n",
    "        res = self.find(root, p.val, q.val)\n",
    "        if self.getP and self.getQ:\n",
    "            return res\n",
    "        return None\n",
    "    def find(self, root, val1, val2):\n",
    "        if root == None:\n",
    "            return None\n",
    "        left = self.find(root.left, val1, val2)\n",
    "        right = self.find(root.right, val1, val2)\n",
    "        if left and right:\n",
    "            return root\n",
    "        if root.val == val1 or root.val == val2:\n",
    "            if root.val == val1:\n",
    "                self.getP = True\n",
    "            if root.val == val2:\n",
    "                self.getQ = True\n",
    "            return root\n",
    "        return left if left else right\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':\n",
    "        def dfs(node, p, q):\n",
    "            if not node:\n",
    "                return (None, 0)\n",
    "            left, left_count = dfs(node.left, p, q)\n",
    "            right, right_count = dfs(node.right, p, q)\n",
    "            if node == p or node == q:\n",
    "                return (node, left_count+right_count+1)\n",
    "            if left and right:\n",
    "                return (node, left_count+right_count)\n",
    "            if left:\n",
    "                return (left, left_count)\n",
    "            if right:\n",
    "                return (right, right_count)\n",
    "            return (None, 0)\n",
    "        ancestor, cnt = dfs(root, p, q)\n",
    "        if cnt == 2:\n",
    "            return ancestor\n",
    "        else:\n",
    "            return \n",
    "\n",
    "\n",
    "\n",
    "        \n",
    "        # def dfs(node, p, q):\n",
    "        #     if not node:\n",
    "        #         return None, 0\n",
    "        #     left, left_cnt = dfs(node.left, p, q)\n",
    "        #     right, right_cnt = dfs(node.right, p, q)\n",
    "        #     if node == p or node == q:\n",
    "        #         return node, 1 + left_cnt + right_cnt\n",
    "        #     if left and right:\n",
    "        #         return node, left_cnt + right_cnt\n",
    "        #     if left:\n",
    "        #         return left, left_cnt\n",
    "        #     if right:\n",
    "        #         return right, right_cnt\n",
    "        #     return None, 0\n",
    "        # node, cnt = dfs(root, p, q)\n",
    "        # if cnt == 2:\n",
    "        #     return node\n",
    "        # else:\n",
    "        #     return \n",
    "            \n",
    "            \n",
    "        \n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    # Time O(n) Space O(n)\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':\n",
    "        self.found = 0\n",
    "        res = self.dfs(root, p, q)\n",
    "        return res if self.found == 2 else None\n",
    "\n",
    "    def dfs(self, root, p, q):\n",
    "        if not root: return None\n",
    "        # should go deeper first to search for the other nodes\n",
    "        left, right = self.dfs(root.left, p, q), self.dfs(root.right, p, q)\n",
    "        # if root is one of the nodes, return with found += 1\n",
    "        if root == p or root == q:\n",
    "            self.found += 1\n",
    "            return root\n",
    "        if left and right: return root\n",
    "        elif not left and right: return right\n",
    "        elif left and not right: return left\n",
    "        else: return None"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':\n",
    "        if not root or not p or not q:\n",
    "            return None\n",
    "        find_p_q = [False, False]\n",
    "        def lca(root, p, q):\n",
    "            if not root:\n",
    "                return None\n",
    "            if root.val == p.val:\n",
    "                find_p_q[0] = True\n",
    "            if root.val == q.val:\n",
    "                find_p_q[1] = True\n",
    "            left = lca(root.left, p, q)\n",
    "            right = lca(root.right, p, q)\n",
    "            if root in (p, q) or (left and right):\n",
    "                return root\n",
    "            else:\n",
    "                return left or right \n",
    "        res = lca(root, p, q) # must run this line first\n",
    "        if find_p_q == [True, True]: # [False, True] -> none\n",
    "            return res\n",
    "        return None\n",
    "       \n",
    "\n",
    "\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':\n",
    "        self.findp, self.findq = False, False\n",
    "        result = self.find(root, p, q)\n",
    "        if self.findp and self.findq:\n",
    "            return result\n",
    "        return None\n",
    "\n",
    "\n",
    "    def find(self, root, p, q):\n",
    "        if not root:\n",
    "            return None\n",
    "        left = self.find(root.left, p, q)\n",
    "        right = self.find(root.right, p, q)\n",
    "\n",
    "        if left and right:\n",
    "            return root\n",
    "        if root==p or root==q:\n",
    "            if root==p:\n",
    "                self.findp = True\n",
    "            if root==q:\n",
    "                self.findq = True\n",
    "            return root\n",
    "        if left and not right:\n",
    "            return left\n",
    "        if right and not left:\n",
    "            return right\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':\n",
    "        self.findp = False\n",
    "        self.findq = False\n",
    "        root = self.find(root, p.val, q.val)\n",
    "        if self.findp and self.findq:\n",
    "            return root\n",
    "        else:\n",
    "            return None\n",
    "\n",
    "    def find(self, root, v1, v2):\n",
    "        if not root:\n",
    "            return None\n",
    "        left = self.find(root.left, v1, v2)\n",
    "        right = self.find(root.right, v1, v2)\n",
    "        if root.val == v1:\n",
    "            self.findp = True\n",
    "            return root\n",
    "        elif root.val == v2:\n",
    "            self.findq = True\n",
    "            return root\n",
    "\n",
    "        if left and right:\n",
    "            return root\n",
    "        if left:\n",
    "            return left\n",
    "        else:\n",
    "            return right\n",
    "        \n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':\n",
    "        # time complexity: O(n)\n",
    "        # space complexity: O(n)\n",
    "        self.p = False\n",
    "        self.q = False\n",
    "       \n",
    "        def find_node(node):\n",
    "            if not node:\n",
    "                return \n",
    "            if node == p:\n",
    "                self.p = True\n",
    "            if node == q:\n",
    "                self.q = True\n",
    "            \n",
    "            if node.left:\n",
    "                find_node(node.left)\n",
    "            if node.right:\n",
    "                find_node(node.right)\n",
    "        \n",
    "        def find_LCR(node):\n",
    "            # if root == p or root == q的检查目的：\n",
    "            # 向上通知：当我们在递归过程中找到了p或q，我们要通知上层的调用（即在递归树中的父调用）我们已经找到了其中一个节点。这是通过返回非None值（在这里是root）来实现的。\n",
    "            # 确定公共祖先：当我们在左子树和右子树递归中都得到了非None的返回值，说明我们在两边分别找到了p和q，此时当前的root就是最近的公共祖先。如果我们只在一边找到了p或q，那么我们会继续向上返回找到的这一个节点，等待在上层中可能找到另一个节点\n",
    "            if not node or node == p or node == q:\n",
    "                return node\n",
    "            \n",
    "            left = find_LCR(node.left)\n",
    "            right = find_LCR(node.right)\n",
    "\n",
    "            if left and right:\n",
    "                return node\n",
    "            \n",
    "            elif left and not right:\n",
    "                return left\n",
    "            elif not left and right:\n",
    "                return right\n",
    "            else:\n",
    "                return None\n",
    "\n",
    "        find_node(root)\n",
    "        if not self.p or not self.q:\n",
    "            return None\n",
    "        \n",
    "        return find_LCR(root)\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':\n",
    "        p_flag, q_flag = False, False\n",
    "\n",
    "        def dfs(root, p, q):\n",
    "            if not root: return root\n",
    "            nonlocal p_flag\n",
    "            nonlocal q_flag\n",
    "            left, right = dfs(root.left, p, q), dfs(root.right, p, q)\n",
    "            if left is not None and right is not None:\n",
    "                return root\n",
    "            \n",
    "            if root.val == p.val:\n",
    "                p_flag = True\n",
    "                return root\n",
    "            elif root.val == q.val:\n",
    "                q_flag = True\n",
    "                return root\n",
    "            \n",
    "            return left if left is not None else right\n",
    "\n",
    "        res = dfs(root, p, q)\n",
    "        if not p_flag or not q_flag:\n",
    "            return None\n",
    "        return res\n",
    "\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':\n",
    "        self.q = False\n",
    "        self.p = False\n",
    "\n",
    "        def tree(root, p, q):\n",
    "            if not root:\n",
    "                return\n",
    "\n",
    "            left = tree(root.left, p, q)\n",
    "            right = tree(root.right, p, q)\n",
    "\n",
    "            if root==p or root==q:\n",
    "                if root==p:\n",
    "                    self.p = True\n",
    "                else:\n",
    "                    self.q = True\n",
    "                return root\n",
    "                \n",
    "            if left and right:\n",
    "                return root\n",
    "            return left or right\n",
    "\n",
    "        res = tree(root, p, q)\n",
    "        if not self.q or not self.p:\n",
    "            return \n",
    "        else:\n",
    "            return res\n",
    "            \n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    \n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':\n",
    "        ans=None\n",
    "        def dfs(node,p,q):\n",
    "            nonlocal ans\n",
    "            if not node:\n",
    "                return False   \n",
    "            left=dfs(node.left,p,q)\n",
    "            right=dfs(node.right,p,q)\n",
    "            if left and  right :\n",
    "                ans=node   \n",
    "            elif left and (node==p or node==q):\n",
    "                ans=node  \n",
    "            elif right and  (node==p or node==q):\n",
    "                ans=node   \n",
    "            return node==p or node==q or left or right\n",
    "        dfs(root,p,q)\n",
    "        return ans\n",
    "\n",
    "            \n",
    "        \n",
    "                \n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':\n",
    "\n",
    "        def helper(root, p, q):\n",
    "            if not root:\n",
    "                return None\n",
    "            left = helper(root.left, p, q)\n",
    "            right = helper(root.right, p, q)\n",
    "            if left and right:\n",
    "                return root\n",
    "            if root == p or root == q:\n",
    "                if root == p:\n",
    "                    self.findP = True\n",
    "                if root == q:\n",
    "                    self.findQ = True\n",
    "                return root\n",
    "            return left if left else right\n",
    "\n",
    "        self.findP = False\n",
    "        self.findQ = False\n",
    "        res = helper(root, p, q)\n",
    "        if self.findP and self.findQ:\n",
    "            return res\n",
    "        else:\n",
    "            return None\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':\n",
    "        \n",
    "\n",
    "        def search(root, p, q):\n",
    "            if root is None:\n",
    "                return None, 0\n",
    "\n",
    "            node_l, cnt_l = search(root.left, p, q)\n",
    "            node_r, cnt_r = search(root.right, p, q)\n",
    "            # print(root.val, cnt_l, cnt_r)\n",
    "            \n",
    "            if (cnt_l == 1 and cnt_r == 1) or ({root, node_l} == {p, q}) or ({root, node_r} == {p, q}):\n",
    "                return root, 2\n",
    "            \n",
    "            elif cnt_l >0:\n",
    "                return node_l, cnt_l\n",
    "            elif cnt_r >0:\n",
    "                return node_r, cnt_r\n",
    "\n",
    "            elif root in (p, q):\n",
    "                return root, 1\n",
    "            else:\n",
    "                return None, 0\n",
    "            \n",
    "\n",
    "        ans,cnt = search(root, p, q)\n",
    "\n",
    "        if cnt == 2:\n",
    "            return ans\n",
    "        else:\n",
    "            return None  \n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':\n",
    "        \n",
    "        def dfs(node, p, q):\n",
    "            if not node:\n",
    "                return None, 0\n",
    "            left, left_cnt = dfs(node.left, p, q)\n",
    "            right, right_cnt = dfs(node.right, p, q)\n",
    "            if node == p or node == q:\n",
    "                return node, 1 + left_cnt + right_cnt\n",
    "            if left and right:\n",
    "                return node, left_cnt + right_cnt\n",
    "            if left:\n",
    "                return left, left_cnt\n",
    "            if right:\n",
    "                return right, right_cnt\n",
    "            return None, 0\n",
    "        node, cnt = dfs(root, p, q)\n",
    "        if cnt == 2:\n",
    "            return node\n",
    "        else:\n",
    "            return \n",
    "            \n",
    "            \n",
    "        \n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def helper(self, root, p, q) -> int:\n",
    "        if not root:\n",
    "            return 0\n",
    "\n",
    "        left = self.helper(root.left, p, q)\n",
    "        right = self.helper(root.right, p, q)\n",
    "        \n",
    "        if root == p or root  == q:\n",
    "            res = left+right+1\n",
    "        else:\n",
    "            res = left+right \n",
    "        if res == 2 and not self.lca:\n",
    "            self.lca = root\n",
    "        return res\n",
    "    \n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':\n",
    "        self.lca = None\n",
    "        self.helper(root, p, q)\n",
    "        return self.lca   "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    found_p = False\n",
    "    found_q = False\n",
    "    \"\"\"\n",
    "    如果p或q之一不存在于该二叉树中，返回null p和q不一定都存在，因此标准中的第二种情况不再适用。\n",
    "    \"\"\"\n",
    "    def find(self, root, p, q):\n",
    "        if not root:\n",
    "            return \n",
    "  \n",
    "        left = self.find(root.left, p, q)\n",
    "        right = self.find(root.right, p, q)\n",
    "        # 如果左右子树中都找到了，说明当前节点是他们的祖先\n",
    "        if left and right:\n",
    "            return root\n",
    "        # 后序位置，判断当前节点是不是目标值\n",
    "    \n",
    "        # 对下面具体说明一下：\n",
    "        # 当左右子树不同时存在时，剩下的情况还有两种：\n",
    "        # 只有其中一个树有：root也有，那么root就是lca，那么返回root即可；root没有，返回left or right\n",
    "        # 都没有：看看root有没，有的话还需要记录下是哪个\n",
    "        \n",
    "        elif left or right:\n",
    "            if root == p or root == q:\n",
    "                if root == p:\n",
    "                    self.found_p = True\n",
    "                if root == q:\n",
    "                    self.found_q = True\n",
    "                return root\n",
    "            else:\n",
    "                return left if left else right\n",
    "        else:\n",
    "            if root == p or root == q:\n",
    "                # 找到了，记录一下\n",
    "                if root == p:\n",
    "                    self.found_p = True\n",
    "                if root == q:\n",
    "                    self.found_q = True\n",
    "                return root\n",
    "            else:\n",
    "                return None\n",
    "\n",
    "       \n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':\n",
    "        res = self.find(root, p, q)\n",
    "        if self.found_p and self.found_q:\n",
    "            return res\n",
    "        else:\n",
    "            return None\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: TreeNode, p: TreeNode, q: TreeNode) -> TreeNode:\n",
    "        \n",
    "        # 用于记录 p 和 q 是否存在于二叉树中\n",
    "        self.foundP = False\n",
    "        self.foundQ = False\n",
    "\n",
    "        res = self.find(root, p.val, q.val)\n",
    "        if not self.foundP or not self.foundQ:\n",
    "            return None\n",
    "\n",
    "        # p 和 q 都存在二叉树中，才有公共祖先\n",
    "        return res\n",
    "        \n",
    "    # 在二叉树中寻找 val1 和 val2 的最近公共祖先节点\n",
    "    def find(self, root, val1, val2):\n",
    "        if not root:\n",
    "            return None\n",
    "\n",
    "        left = self.find(root.left, val1, val2)\n",
    "        right = self.find(root.right, val1, val2)\n",
    "        \n",
    "        # 后序位置，判断当前节点是不是 LCA 节点\n",
    "        if left and right:\n",
    "            return root\n",
    "        \n",
    "        # 后序位置，判断当前节点是不是目标值\n",
    "        if root.val == val1 or root.val == val2:\n",
    "            # 找到了，记录一下\n",
    "            if root.val == val1:\n",
    "                self.foundP = True\n",
    "            if root.val == val2:\n",
    "                self.foundQ = True\n",
    "            return root\n",
    "\n",
    "        return left if left else right"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def _lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':\n",
    "        if not root:\n",
    "            return None\n",
    "        leftRes = self._lowestCommonAncestor(root.left, p, q)\n",
    "        rightRes = self._lowestCommonAncestor(root.right, p, q)\n",
    "\n",
    "        if root == p:\n",
    "            self.foundP = True\n",
    "            return root\n",
    "        if root == q:\n",
    "            self.foundQ = True\n",
    "            return root\n",
    "\n",
    "        if leftRes and rightRes:\n",
    "            return root\n",
    "        if leftRes:\n",
    "            return leftRes\n",
    "        if rightRes:\n",
    "            return rightRes\n",
    "        return None\n",
    "\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':\n",
    "        self.foundP = False\n",
    "        self.foundQ = False\n",
    "        res = self._lowestCommonAncestor(root, p, q)\n",
    "        return res if self.foundP and self.foundQ else None"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommon(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode'):\n",
    "        if not root:\n",
    "            return None,0\n",
    "        \n",
    "        left_result,cnt = self.lowestCommon(root.left,p,q)\n",
    "\n",
    "        if cnt==2:\n",
    "            return left_result,2\n",
    "\n",
    "        right_result,cnt = self.lowestCommon(root.right,p,q)\n",
    "\n",
    "        if cnt==2:\n",
    "            return right_result,2\n",
    "\n",
    "        if  left_result and  right_result:\n",
    "            return root,2\n",
    "        if root == p or root==q:\n",
    "            if left_result or right_result:\n",
    "                return root,2\n",
    "            return root,1\n",
    "        if not left_result and right_result:\n",
    "            return right_result,1\n",
    "        elif not right_result and left_result:\n",
    "            return left_result,1\n",
    "        return None,0\n",
    "\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode')  -> 'TreeNode':\n",
    "        node,cnt = self.lowestCommon(root,p,q)\n",
    "        if cnt==2:\n",
    "            return node\n",
    "        else:\n",
    "            return None\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':\n",
    "        flag_p, flag_q = False, False\n",
    "        \n",
    "        def search(node):\n",
    "            nonlocal flag_p\n",
    "            nonlocal flag_q\n",
    "            if not node:\n",
    "                return \n",
    "            if node.val == p.val:\n",
    "                flag_p = True \n",
    "            if node.val == q.val:\n",
    "                flag_q = True \n",
    "            search(node.left)\n",
    "            search(node.right)\n",
    "\n",
    "        search(root)\n",
    "        if not (flag_p and flag_q):\n",
    "            return None\n",
    "\n",
    "        def f(root):\n",
    "            if root in [p, q, None]:\n",
    "                return root \n",
    "            l, r = f(root.left), f(root.right)\n",
    "            if not l:\n",
    "                return r \n",
    "            if not r:\n",
    "                return l \n",
    "            return root\n",
    "        \n",
    "        return f(root)\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':\n",
    "        self.flag_p, self.flag_q = False, False\n",
    "        self.dfs(root, p, q)\n",
    "        if not (self.flag_p == True and self.flag_q == True):\n",
    "            return None\n",
    "        return self.dfs_LRN(root, p, q)\n",
    "\n",
    "    def dfs(self, root, p, q) -> None:\n",
    "        if root == p:\n",
    "            self.flag_p = True\n",
    "        if root == q:\n",
    "            self.flag_q = True\n",
    "        if root.left:\n",
    "            self.dfs(root.left, p, q)\n",
    "        if root.right:\n",
    "            self.dfs(root.right, p, q)\n",
    "\n",
    "    def dfs_LRN(self, root, p, q) -> TreeNode:\n",
    "        if root == None or root == p or root == q:\n",
    "            return root\n",
    "        L = self.dfs_LRN(root.left, p, q)\n",
    "        R = self.dfs_LRN(root.right, p, q)\n",
    "        if L and R:\n",
    "            return root \n",
    "        elif L and R == None:\n",
    "            return L\n",
    "        elif L == None and R:\n",
    "            return R\n",
    "        else:\n",
    "            return None"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':\n",
    "        self.q = False\n",
    "        self.p = False\n",
    "\n",
    "        def tree(root, p, q):\n",
    "            if not root:\n",
    "                return\n",
    "\n",
    "            left = tree(root.left, p, q)\n",
    "            right = tree(root.right, p, q)\n",
    "\n",
    "            if left and right:\n",
    "                return root\n",
    "                \n",
    "            if root==p or root==q:\n",
    "                if root==p:\n",
    "                    self.p = True\n",
    "                else:\n",
    "                    self.q = True\n",
    "                return root\n",
    "\n",
    "            return left or right\n",
    "\n",
    "        res = tree(root, p, q)\n",
    "        if not self.q or not self.p:\n",
    "            return \n",
    "        else:\n",
    "            return res\n",
    "            \n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':\n",
    "        if self.check_existence(root, p) and self.check_existence(root, q):\n",
    "            return self.get_common_ancestor(root, p, q)\n",
    "        else:\n",
    "            return None\n",
    "    \n",
    "\n",
    "    def check_existence(self, root: 'TreeNode', target_node: 'TreeNode') -> bool:\n",
    "        if not root:\n",
    "            return False\n",
    "        elif root.val == target_node.val:\n",
    "            return True\n",
    "        else:\n",
    "            left_return = self.check_existence(root.left, target_node)\n",
    "            right_return = self.check_existence(root.right, target_node)\n",
    "\n",
    "            return left_return or right_return\n",
    "\n",
    "    def get_common_ancestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':\n",
    "        if not root or root.val == p.val or root.val == q.val:\n",
    "            return root\n",
    "        else:\n",
    "            left_return = self.get_common_ancestor(root.left, p, q)\n",
    "            right_return = self.get_common_ancestor(root.right, p, q)\n",
    "\n",
    "            if not left_return:\n",
    "                return right_return\n",
    "            elif not right_return:\n",
    "                return left_return\n",
    "            else:\n",
    "                return root"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    Has_P = False\n",
    "    Has_Q = False\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':\n",
    "        node = self.find(root, p, q)\n",
    "        if self.Has_P and self.Has_Q:\n",
    "            return node\n",
    "        return None\n",
    "    \n",
    "    def find(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':\n",
    "        if root is None:\n",
    "            return None\n",
    "        \n",
    "        left = self.find(root.left, p, q)\n",
    "        right = self.find(root.right, p, q)\n",
    "        if left and right:\n",
    "            return root\n",
    "\n",
    "        if root == q:\n",
    "            self.Has_Q = True\n",
    "            return root\n",
    "        \n",
    "        if root == p:\n",
    "            self.Has_P = True\n",
    "            return root\n",
    "        \n",
    "        return left or right"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "class TreeNode:\n",
    "    def __init__(self, x):\n",
    "        self.val = x\n",
    "        self.left = None\n",
    "        self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':\n",
    "        # Step 1: Check if p and q exist in the tree\n",
    "        self.flag_p, self.flag_q = False, False\n",
    "        self.dfs(root, p, q)\n",
    "        if not (self.flag_p == True and self.flag_q == True):\n",
    "            return None\n",
    "        \n",
    "        # Step 2: Find the LCA\n",
    "        return self.dfs_LRN(root, p, q)\n",
    "    \n",
    "    def dfs(self, root, p, q) -> None:  # Check if p and q exist in the tree\n",
    "        if root == p:\n",
    "            self.flag_p = True\n",
    "        if root == q:\n",
    "            self.flag_q = True\n",
    "        if root.left:\n",
    "            self.dfs(root.left, p, q)\n",
    "        if root.right:\n",
    "            self.dfs(root.right, p, q)\n",
    "    \n",
    "    def dfs_LRN(self, root, p, q) -> 'TreeNode':  # Post-order traversal to find LCA\n",
    "        if root == None or root == p or root == q:\n",
    "            return root\n",
    "        L = self.dfs_LRN(root.left, p, q)\n",
    "        R = self.dfs_LRN(root.right, p, q)\n",
    "        if L and R:\n",
    "            return root\n",
    "        elif L and R == None:\n",
    "            return L\n",
    "        elif L == None and R:\n",
    "            return R\n",
    "        else:\n",
    "            return None\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':\n",
    "        def helper(root, p, q):\n",
    "            if not root:\n",
    "                return None, False\n",
    "            \n",
    "            left, l = helper(root.left, p, q)\n",
    "            right, r = helper(root.right, p, q)\n",
    "\n",
    "            if l:\n",
    "                return left, True\n",
    "            if r:\n",
    "                return right,True\n",
    "\n",
    "            if (root.val == p.val or root.val == q.val) and (left or right):\n",
    "                return root, True\n",
    "            elif root.val == p.val or root.val == q.val:\n",
    "                return root, False\n",
    "\n",
    "            if left and right:\n",
    "                return root, True\n",
    "            elif not left and right:\n",
    "                return right, False\n",
    "            elif not right and left:\n",
    "                return left, False\n",
    "            elif not left and not right:\n",
    "                return None, False\n",
    "        \n",
    "        \n",
    "        node, res = helper(root, p, q)\n",
    "        if res:\n",
    "            return node\n",
    "        else:\n",
    "            return None"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution: #这道题没有保证一定存在p和q因此不能在前序位置碰到就反回了，必须完全遍历整颗树\n",
    "    def __init__(self):\n",
    "        self.p = False\n",
    "        self.q = False\n",
    "\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':\n",
    "        ans = self.BackTrack(root, p, q)\n",
    "        if not self.p or not self.q: return None\n",
    "        return ans\n",
    "\n",
    "    def BackTrack(self, root, p, q):\n",
    "        if not root: return\n",
    "        left = self.BackTrack(root.left, p, q)\n",
    "        right = self.BackTrack(root.right, p, q)\n",
    "        if left and right:\n",
    "            return root\n",
    "        if root.val == p.val:\n",
    "            self.p = True\n",
    "            return root\n",
    "        if root.val == q.val:\n",
    "            self.q = True\n",
    "            return root\n",
    "        return left if left else right\n",
    "        \n",
    "\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':\n",
    "        self.findP, self.findQ = False, False\n",
    "        result = self.find(root, p, q)\n",
    "        if self.findP and self.findQ:\n",
    "            return result\n",
    "        return None\n",
    "\n",
    "    def find(self, root, p, q):\n",
    "        if not root:\n",
    "            return None\n",
    "        left = self.find(root.left, p, q)\n",
    "        right = self.find(root.right, p, q)\n",
    "\n",
    "        if left and right:\n",
    "            return root\n",
    "        if root==q or root==p:\n",
    "            if root==p:\n",
    "                self.findP = True\n",
    "            if root==q:\n",
    "                self.findQ = True\n",
    "            return root\n",
    "        if left and not right:\n",
    "            return left\n",
    "        if right and not left:\n",
    "            return right"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':\n",
    "        self.findp = False \n",
    "        self.findq = False \n",
    "\n",
    "        res = self.LCA(root, p, q)\n",
    "\n",
    "        if not self.findp or not self.findq:\n",
    "            return None\n",
    "\n",
    "        return res\n",
    "\n",
    "    def LCA(self, root, p, q):\n",
    "        if root is None:\n",
    "            return None\n",
    "\n",
    "        left = self.LCA(root.left, p, q)\n",
    "        right = self.LCA(root.right, p, q)\n",
    "\n",
    "        if left and right:\n",
    "            return root\n",
    "\n",
    "        if root.val == p.val:\n",
    "            self.findp = True\n",
    "            return root\n",
    "\n",
    "        if root.val == q.val:\n",
    "            self.findq = True\n",
    "            return root\n",
    "\n",
    "        return left if left else right\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':\n",
    "        p_flag = False\n",
    "        q_flag = False\n",
    "\n",
    "        def dfs(root):\n",
    "            nonlocal result, p_flag, q_flag\n",
    "            if root is None:\n",
    "                return root\n",
    "            left = dfs(root.left)\n",
    "            right = dfs(root.right)\n",
    "            if left and right:\n",
    "                return root\n",
    "            if root == p or root == q:\n",
    "                if root == p:\n",
    "                    p_flag = True\n",
    "                if root == q:\n",
    "                    q_flag = True\n",
    "                return root\n",
    "            return left if left else right\n",
    "\n",
    "        result = dfs(root)\n",
    "        if p_flag and q_flag:\n",
    "            return result\n",
    "        return None\n",
    "            \n",
    "\n",
    "    def lowestCommonAncestor2(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':\n",
    "        @lru_cache(maxsize=None)\n",
    "        def is_contain(root, p):\n",
    "            if root is None:\n",
    "                return False\n",
    "            if root == p:\n",
    "                return True\n",
    "            return is_contain(root.left, p) or is_contain(root.right, p)\n",
    "\n",
    "        result = None\n",
    "\n",
    "        def dfs(root, p, q):\n",
    "            nonlocal result\n",
    "            lp, rp = is_contain(root.left, p), is_contain(root.right, p)\n",
    "            lq, rq = is_contain(root.left, q), is_contain(root.right, q)\n",
    "            count = 0\n",
    "            for it in [lp, rp, lq, rq]:\n",
    "                if it is True:\n",
    "                    count += 1\n",
    "            if count == 0:\n",
    "                return\n",
    "            if count == 1:\n",
    "                if root == p or root == q:\n",
    "                    result = root\n",
    "                return\n",
    "            # print(root.val, lp, rp, lq, rq)\n",
    "            if (lp is True and lq is False) or (lp is False and lq is True):\n",
    "                result = root\n",
    "                return\n",
    "            if lp is True:\n",
    "                dfs(root.left, p, q)\n",
    "            else:\n",
    "                dfs(root.right, p, q)\n",
    "\n",
    "        dfs(root, p, q)\n",
    "        return result\n",
    "\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':\n",
    "        def helper(root, p, q):\n",
    "            if not root:\n",
    "                return None\n",
    "            \n",
    "            left = helper(root.left, p, q)\n",
    "            right = helper(root.right, p, q)\n",
    "            if root.val == p.val or root.val == q.val:\n",
    "                return root\n",
    "            if left and right:\n",
    "                return root\n",
    "            if left:\n",
    "                return left\n",
    "            if right:\n",
    "                return right\n",
    "            return None\n",
    "            \n",
    "        def findTarget(root, target):\n",
    "            if not root:\n",
    "                return \n",
    "            if root.val == target.val:\n",
    "                return root\n",
    "            \n",
    "            left = findTarget(root.left, target)\n",
    "            right = findTarget(root.right, target)\n",
    "\n",
    "            if left != None:\n",
    "                return left\n",
    "            else:\n",
    "                return right\n",
    "\n",
    "            \n",
    "            \n",
    "        isP, isQ = findTarget(root, p), findTarget(root, q)\n",
    "\n",
    "        if not isP or not isQ:\n",
    "            return None\n",
    "        \n",
    "        return helper(root, isP, isQ)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    found_p = False\n",
    "    found_q = False\n",
    "    \"\"\"\n",
    "    如果p或q之一不存在于该二叉树中，返回null p和q不一定都存在，因此标准中的第二种情况不再适用。\n",
    "    \"\"\"\n",
    "    def find(self, root, p, q):\n",
    "        if not root:\n",
    "            return \n",
    "  \n",
    "        left = self.find(root.left, p, q)\n",
    "        right = self.find(root.right, p, q)\n",
    "        # 如果左右子树中都找到了，说明当前节点是他们的祖先\n",
    "        if left and right:\n",
    "            return root\n",
    "        # 后序位置，判断当前节点是不是目标值\n",
    "    \n",
    "        # 对下面具体说明一下：\n",
    "        # 当左右子树不同时存在时，剩下的情况还有两种：\n",
    "        # 只有其中一个树有：root也有，那么root就是lca，那么返回root即可；root没有，返回left or right\n",
    "        # 都没有：看看root有没，有的话还需要记录下是哪个\n",
    "        \n",
    "        elif left or right:\n",
    "            if root == p or root == q:\n",
    "                if root == p:\n",
    "                    self.found_p = True\n",
    "                if root == q:\n",
    "                    self.found_q = True\n",
    "                return root\n",
    "            else:\n",
    "                return left if left else right\n",
    "        else:\n",
    "            if root == p or root == q:\n",
    "                # 找到了，记录一下\n",
    "                if root == p:\n",
    "                    self.found_p = True\n",
    "                if root == q:\n",
    "                    self.found_q = True\n",
    "                return root\n",
    "            else:\n",
    "                return None\n",
    "\n",
    "       \n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':\n",
    "        res = self.find(root, p, q)\n",
    "        if self.found_p and self.found_q:\n",
    "            return res\n",
    "        else:\n",
    "            return None\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':\n",
    "        self.foundP, self.foundQ = False, False\n",
    "        node = self.find(root, p, q)\n",
    "        if not self.foundP or not self.foundQ:\n",
    "            return None\n",
    "        return node\n",
    "\n",
    "    \n",
    "    def find(self, node:'TreeNode', p:'TreeNode', q:'Treenode') -> bool:\n",
    "        if not node:\n",
    "            return None\n",
    "\n",
    "        left = self.find(node.left, p, q)\n",
    "        right = self.find(node.right, p, q)\n",
    "\n",
    "        # 左右都找到了一个节点，说明当前节点就是 LCA 节点\n",
    "        if left and right:\n",
    "            return node\n",
    "\n",
    "        # 节点匹配并且做标记\n",
    "        if node is p or node is q:\n",
    "            if node is p:\n",
    "                self.foundP = True\n",
    "            if node is q:\n",
    "                self.foundQ = True\n",
    "            return node\n",
    "\n",
    "        # 向上传递找到的节点\n",
    "        return left if left else right"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def _lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':\n",
    "        if not root:\n",
    "            return None\n",
    "        leftRes = self._lowestCommonAncestor(root.left, p, q)\n",
    "        rightRes = self._lowestCommonAncestor(root.right, p, q)\n",
    "\n",
    "        if root == p:\n",
    "            self.foundP = True\n",
    "            return root\n",
    "        if root == q:\n",
    "            self.foundQ = True\n",
    "            return root\n",
    "\n",
    "        if leftRes and rightRes:\n",
    "            return root\n",
    "        if leftRes:\n",
    "            return leftRes\n",
    "        if rightRes:\n",
    "            return rightRes\n",
    "        return None\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':\n",
    "        self.foundP = False\n",
    "        self.foundQ = False\n",
    "        res = self._lowestCommonAncestor(root, p, q)\n",
    "        print (self.foundP)\n",
    "        print (self.foundQ)\n",
    "        return res if self.foundP and self.foundQ else None"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def __init__(self):\n",
    "        self.get_p = False\n",
    "        self.get_q = False\n",
    "\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':\n",
    "        res = self.find(root, p.val, q.val)\n",
    "        if self.get_p and self.get_q:\n",
    "            return res\n",
    "\n",
    "        return None\n",
    "\n",
    "    def find(self, root, val1, val2):\n",
    "        if not root:\n",
    "            return None\n",
    "        \n",
    "        left= self.find(root.left, val1, val2)\n",
    "        right = self.find(root.right, val1, val2)\n",
    "\n",
    "        if left and right:\n",
    "            return root\n",
    "\n",
    "        if root.val == val1 or root.val == val2:\n",
    "            if root.val == val1:\n",
    "                self.get_p = True\n",
    "            \n",
    "            if root.val == val2:\n",
    "                self.get_q = True\n",
    "            \n",
    "            return root\n",
    "        \n",
    "        return left if left else right\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':\n",
    "        ret = []\n",
    "        def countCommonAncestor(root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> int:\n",
    "            if not root:\n",
    "                return 0\n",
    "            count = 0\n",
    "            if root == p or root == q:\n",
    "                count = 1\n",
    "            count += countCommonAncestor(root.left, p, q)\n",
    "            if ret:\n",
    "                return 2\n",
    "            if count < 2:\n",
    "                count += countCommonAncestor(root.right, p, q)\n",
    "            if count == 2:\n",
    "                ret.append(root)\n",
    "            return count\n",
    "        countCommonAncestor(root, p, q)\n",
    "        if ret:\n",
    "            return ret[0]\n",
    "        return None"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':\n",
    "        p_flag = False\n",
    "        q_flag = False\n",
    "\n",
    "        def dfs(root):\n",
    "            nonlocal result, p_flag, q_flag\n",
    "            if root is None:\n",
    "                return root\n",
    "            left = dfs(root.left)\n",
    "            right = dfs(root.right)\n",
    "            if root == p or root == q:\n",
    "                if root == p:\n",
    "                    p_flag = True\n",
    "                if root == q:\n",
    "                    q_flag = True\n",
    "                return root\n",
    "            if left and right:\n",
    "                return root\n",
    "            return left if left else right\n",
    "\n",
    "        result = dfs(root)\n",
    "        if p_flag and q_flag:\n",
    "            return result\n",
    "        return None\n",
    "            \n",
    "\n",
    "    def lowestCommonAncestor2(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':\n",
    "        @lru_cache(maxsize=None)\n",
    "        def is_contain(root, p):\n",
    "            if root is None:\n",
    "                return False\n",
    "            if root == p:\n",
    "                return True\n",
    "            return is_contain(root.left, p) or is_contain(root.right, p)\n",
    "\n",
    "        result = None\n",
    "\n",
    "        def dfs(root, p, q):\n",
    "            nonlocal result\n",
    "            lp, rp = is_contain(root.left, p), is_contain(root.right, p)\n",
    "            lq, rq = is_contain(root.left, q), is_contain(root.right, q)\n",
    "            count = 0\n",
    "            for it in [lp, rp, lq, rq]:\n",
    "                if it is True:\n",
    "                    count += 1\n",
    "            if count == 0:\n",
    "                return\n",
    "            if count == 1:\n",
    "                if root == p or root == q:\n",
    "                    result = root\n",
    "                return\n",
    "            # print(root.val, lp, rp, lq, rq)\n",
    "            if (lp is True and lq is False) or (lp is False and lq is True):\n",
    "                result = root\n",
    "                return\n",
    "            if lp is True:\n",
    "                dfs(root.left, p, q)\n",
    "            else:\n",
    "                dfs(root.right, p, q)\n",
    "\n",
    "        dfs(root, p, q)\n",
    "        return result\n",
    "\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':\n",
    "        lst = []\n",
    "        def dfs(node):\n",
    "            if node == None:\n",
    "                return \n",
    "            lst.append(node)\n",
    "            if node.left:dfs(node.left)\n",
    "            if node.right:dfs(node.right)\n",
    "        dfs(root)\n",
    "        if p not in lst or q not in lst:\n",
    "            return None\n",
    "        def dfs2(node, p, q):\n",
    "            if node in (None, p, q):\n",
    "                return node\n",
    "            left = dfs2(node.left, p, q)\n",
    "            right = dfs2(node.right, p, q)\n",
    "            if left and right:\n",
    "                return node\n",
    "            return left or right\n",
    "        return dfs2(root, p, q)\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':\n",
    "        def lca(root, p, q):\n",
    "            if not root:\n",
    "                return None, None\n",
    "            left1, left2 = lca(root.left, p, q)\n",
    "            right1, right2 = lca(root.right, p, q)\n",
    "            if left1 != None:\n",
    "                final1 = left1\n",
    "            elif right1 != None:\n",
    "                final1 = right1\n",
    "            else:\n",
    "                final1 = None\n",
    "            if left2 != None:\n",
    "                final2 = left2\n",
    "            elif right2 != None:\n",
    "                final2 = right2\n",
    "            else:\n",
    "                final2 = None\n",
    "            if root == p:\n",
    "                final1 = root\n",
    "            if root == q:\n",
    "                final2 = root\n",
    "            if final1 == final2 and final1 != None:\n",
    "                return final1, final2\n",
    "            if final1 != None and final2 != None:\n",
    "                return root, root\n",
    "            else:\n",
    "                return final1, final2\n",
    "        final1, final2 = lca(root, p, q)\n",
    "        if final1 == final2 and final1 != None:\n",
    "            return final1\n",
    "        else:\n",
    "            return None"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':\n",
    "        p_exist, q_exist, lac = self.recursion(root, p, q)\n",
    "        if not p_exist or not q_exist:\n",
    "            return None\n",
    "        return lac\n",
    "    \n",
    "    def recursion(self, root, p, q):\n",
    "        if not root:\n",
    "            return False, False, None\n",
    "        \n",
    "        left_p_exist, left_q_exist, left_node = self.recursion(root.left, p, q)\n",
    "        right_p_exist, right_q_exist, right_node = self.recursion(root.right, p, q)\n",
    "\n",
    "        p_exist = left_p_exist or right_p_exist or root == p\n",
    "        q_exist = left_q_exist or right_q_exist or root == q\n",
    "\n",
    "        if root == q or root == p:\n",
    "            return p_exist, q_exist, root\n",
    "        \n",
    "        if left_node and right_node:\n",
    "            return p_exist, q_exist, root\n",
    "        \n",
    "        if left_node:\n",
    "            return p_exist, q_exist, left_node\n",
    "\n",
    "        if right_node:\n",
    "            return p_exist, q_exist, right_node\n",
    "        \n",
    "        return p_exist, q_exist, None\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':\n",
    "        p_exist, q_exist, lac = self.recursion(root, p, q)\n",
    "        if not p_exist or not q_exist:\n",
    "            return None\n",
    "        return lac\n",
    "    \n",
    "    def recursion(self, root, p, q):\n",
    "        if not root:\n",
    "            return False, False, None\n",
    "        \n",
    "        left_p_exist, left_q_exist, left_node = self.recursion(root.left, p, q)\n",
    "        right_p_exist, right_q_exist, right_node = self.recursion(root.right, p, q)\n",
    "\n",
    "        p_exist = left_p_exist or right_p_exist or root == p\n",
    "        q_exist = left_q_exist or right_q_exist or root == q\n",
    "\n",
    "        if root == q or root == p:\n",
    "            return p_exist, q_exist, root\n",
    "        \n",
    "        if left_node and right_node:\n",
    "            return p_exist, q_exist, root\n",
    "        \n",
    "        if left_node:\n",
    "            return p_exist, q_exist, left_node\n",
    "\n",
    "        if right_node:\n",
    "            return p_exist, q_exist, right_node\n",
    "        \n",
    "        return p_exist, q_exist, None\n",
    "\n",
    "# 作者：已注销\n",
    "# 链接：https://leetcode.cn/problems/lowest-common-ancestor-of-a-binary-tree-ii/solutions/1417938/by-silencer-3-bl0u/\n",
    "# 来源：力扣（LeetCode）\n",
    "# 著作权归作者所有。商业转载请联系作者获得授权，非商业转载请注明出处。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':\n",
    "        p_exist, q_exist, lac = self.recursion(root, p, q)\n",
    "        if not p_exist or not q_exist:\n",
    "            return None\n",
    "        return lac\n",
    "    \n",
    "    def recursion(self, root, p, q):\n",
    "        if not root:\n",
    "            return False, False, None\n",
    "        \n",
    "        left_p_exist, left_q_exist, left_node = self.recursion(root.left, p, q)\n",
    "        right_p_exist, right_q_exist, right_node = self.recursion(root.right, p, q)\n",
    "\n",
    "        p_exist = left_p_exist or right_p_exist or root == p\n",
    "        q_exist = left_q_exist or right_q_exist or root == q\n",
    "\n",
    "        if root == q or root == p:\n",
    "            return p_exist, q_exist, root\n",
    "        \n",
    "        if left_node and right_node:\n",
    "            return p_exist, q_exist, root\n",
    "        \n",
    "        if left_node:\n",
    "            return p_exist, q_exist, left_node\n",
    "\n",
    "        if right_node:\n",
    "            return p_exist, q_exist, right_node\n",
    "        \n",
    "        return p_exist, q_exist, None\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':\n",
    "        p_exist, q_exist, lac = self.recursion(root, p, q)\n",
    "        if not p_exist or not q_exist:\n",
    "            return None\n",
    "        return lac\n",
    "    \n",
    "    def recursion(self, root, p, q):\n",
    "        if not root:\n",
    "            return False, False, None\n",
    "        \n",
    "        left_p_exist, left_q_exist, left_node = self.recursion(root.left, p, q)\n",
    "        right_p_exist, right_q_exist, right_node = self.recursion(root.right, p, q)\n",
    "\n",
    "        p_exist = left_p_exist or right_p_exist or root == p\n",
    "        q_exist = left_q_exist or right_q_exist or root == q\n",
    "\n",
    "        if root == q or root == p:\n",
    "            return p_exist, q_exist, root\n",
    "        \n",
    "        if left_node and right_node:\n",
    "            return p_exist, q_exist, root\n",
    "        \n",
    "        if left_node:\n",
    "            return p_exist, q_exist, left_node\n",
    "\n",
    "        if right_node:\n",
    "            return p_exist, q_exist, right_node\n",
    "        \n",
    "        return p_exist, q_exist, None\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':\n",
    "        p_exists, q_exists, lca = self.helper(root, p, q)\n",
    "        return lca if p_exists and q_exists else None\n",
    "    \n",
    "    def helper(self, root, p, q):\n",
    "        if not root: return False, False, None\n",
    "        p_exists_in_left, q_exists_in_left, left_lca = self.helper(root.left, p, q)\n",
    "        p_exists_in_right, q_exists_in_right, right_lca = self.helper(root.right, p, q)\n",
    "\n",
    "        p_exists = p_exists_in_left or p_exists_in_right or root == p\n",
    "        q_exists = q_exists_in_left or q_exists_in_right or root == q\n",
    "\n",
    "        if root == p or root == q:\n",
    "            return p_exists, q_exists, root\n",
    "        \n",
    "        if left_lca and right_lca:\n",
    "            return p_exists, q_exists, root\n",
    "        if left_lca:\n",
    "            return p_exists, q_exists, left_lca\n",
    "        if right_lca:\n",
    "            return p_exists, q_exists, right_lca\n",
    "        \n",
    "        return p_exists, q_exists, None\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':\n",
    "        p_exists, q_exists, lca = self.helper(root, p, q)\n",
    "        return lca if p_exists and q_exists else None\n",
    "    \n",
    "    def helper(self, root, p, q):\n",
    "        if not root: return False, False, None\n",
    "        p_exists_in_left, q_exists_in_left, left_lca = self.helper(root.left, p, q)\n",
    "        p_exists_in_right, q_exists_in_right, right_lca = self.helper(root.right, p, q)\n",
    "\n",
    "        p_exists = p_exists_in_left or p_exists_in_right or root == p\n",
    "        q_exists = q_exists_in_left or q_exists_in_right or root == q\n",
    "\n",
    "        if root == p or root == q:\n",
    "            return p_exists, q_exists, root\n",
    "        if left_lca and right_lca:\n",
    "            return p_exists, q_exists, root\n",
    "\n",
    "        if left_lca:\n",
    "            return p_exists, q_exists, left_lca\n",
    "        if right_lca:\n",
    "            return p_exists, q_exists, right_lca\n",
    "        \n",
    "        return p_exists, q_exists, None"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':\n",
    "        result=None\n",
    "\n",
    "        def method(node,p_node,q_node):\n",
    "            \n",
    "            nonlocal result\n",
    "            nonlocal p\n",
    "            nonlocal q\n",
    "            if node==None:\n",
    "                return None, None\n",
    "            else:\n",
    "\n",
    "                if node==p and p_node==None:\n",
    "                    p_node=node\n",
    "                    if q_node==q and result==None:\n",
    "                        result=q\n",
    "\n",
    "                elif node==q and q_node==None:\n",
    "                    q_node=node\n",
    "                    if p_node==p and result==None:\n",
    "                        result=p\n",
    "                \n",
    "                left_p,left_q=method(node.left,p_node,q_node)\n",
    "                right_p,right_q=method(node.right,p_node,q_node)\n",
    "                if left_p==p and right_q==q and left_q==None and right_p==None and result==None:\n",
    "                    result=node\n",
    "                if left_q==q and right_p==p and left_p==None and right_q==None and result==None:\n",
    "                    result=node\n",
    "\n",
    "                p_r=None\n",
    "                q_r=None\n",
    "                for n in [p_node,left_p,right_p]:\n",
    "                    if n==p:\n",
    "                        p_r=n\n",
    "                for n in [q_node,left_q,right_q]:\n",
    "                    if n==q:\n",
    "                        q_r=n                \n",
    "                return p_r,q_r\n",
    "\n",
    "        method(root,None,None)\n",
    "        return result\n",
    "\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':\n",
    "        p_exist, q_exist, lac = self.recursion(root, p, q)\n",
    "        if not p_exist or not q_exist:\n",
    "            return None\n",
    "        return lac\n",
    "    \n",
    "    def recursion(self, root, p, q):\n",
    "        if not root:\n",
    "            return False, False, None\n",
    "        \n",
    "        left_p_exist, left_q_exist, left_node = self.recursion(root.left, p, q)\n",
    "        right_p_exist, right_q_exist, right_node = self.recursion(root.right, p, q)\n",
    "\n",
    "        p_exist = left_p_exist or right_p_exist or root == p\n",
    "        q_exist = left_q_exist or right_q_exist or root == q\n",
    "\n",
    "        if root == q or root == p:\n",
    "            return p_exist, q_exist, root\n",
    "        \n",
    "        if left_node and right_node:\n",
    "            return p_exist, q_exist, root\n",
    "        \n",
    "        if left_node:\n",
    "            return p_exist, q_exist, left_node\n",
    "\n",
    "        if right_node:\n",
    "            return p_exist, q_exist, right_node\n",
    "        \n",
    "        return p_exist, q_exist, None\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':\n",
    "        curr=root  \n",
    "        seen=set([root])\n",
    "        ans=None\n",
    "        def dfs(node,target,first):\n",
    "            nonlocal ans\n",
    "            if node==target:\n",
    "                if first:\n",
    "                    seen.add(node)\n",
    "                elif node in seen:\n",
    "                    \n",
    "                    ans=node\n",
    "                return True\n",
    "            else:\n",
    "                if node.left:\n",
    "                    res=dfs(node.left,target,first)\n",
    "                    if res:\n",
    "                        if first:\n",
    "                            seen.add(node.left)\n",
    "                        elif node in seen and not ans:\n",
    "                            \n",
    "                            ans=node\n",
    "                        return True\n",
    "                if node.right:\n",
    "                    res=dfs(node.right,target,first)\n",
    "                    if res:\n",
    "                        if first:\n",
    "                            seen.add(node.right)\n",
    "                        elif node in seen and not ans:\n",
    "                            \n",
    "                            ans=node\n",
    "                        return True\n",
    "            return False\n",
    "        if dfs(root,p,True) and dfs(root,q,False):\n",
    "        \n",
    "      #  print(seen)\n",
    "            return ans    \n",
    "        \n",
    "                \n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':\n",
    "        a, b, pth = None, None, []\n",
    "        def print_path(n):\n",
    "            nonlocal a, b\n",
    "            pth.append(n)\n",
    "            if n.val == p.val:\n",
    "                a = pth.copy()\n",
    "            elif n.val == q.val:\n",
    "                b = pth.copy()\n",
    "\n",
    "            if n.left:\n",
    "                print_path(n.left)\n",
    "            if n.right:\n",
    "                print_path(n.right)\n",
    "            pth.pop() \n",
    "            if a and b:\n",
    "                return\n",
    "\n",
    "        print_path(root)\n",
    "        if not a or not b:\n",
    "            return None\n",
    "        i, j = 0, 0\n",
    "        while True:\n",
    "            if i >= len(a) or j >= len(b) or a[i].val != b[j].val:\n",
    "                return a[i-1]\n",
    "            else:\n",
    "                i += 1\n",
    "                j += 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':\n",
    "        a, b, pth = None, None, []\n",
    "        def print_path(n):\n",
    "            nonlocal a, b\n",
    "            pth.append(n)\n",
    "            if n.val == p.val:\n",
    "                a = pth.copy()\n",
    "            elif n.val == q.val:\n",
    "                b = pth.copy()\n",
    "\n",
    "            if n.left:\n",
    "                print_path(n.left)\n",
    "            if n.right:\n",
    "                print_path(n.right)\n",
    "            aa = pth.pop() \n",
    "            if a and b:\n",
    "                return\n",
    "\n",
    "        print_path(root)\n",
    "        if not a or not b:\n",
    "            return None\n",
    "        i, j = 0, 0\n",
    "        while True:\n",
    "            if i >= len(a) or j >= len(b) or a[i].val != b[j].val:\n",
    "                return a[i-1]\n",
    "            else:\n",
    "                i += 1\n",
    "                j += 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':\n",
    "        a, b, pth = [], [], []\n",
    "        def print_path(n):\n",
    "            nonlocal a, b\n",
    "            pth.append(n)\n",
    "            if n.val == p.val:\n",
    "                a = pth.copy()\n",
    "            elif n.val == q.val:\n",
    "                b = pth.copy()\n",
    "\n",
    "            if n.left:\n",
    "                print_path(n.left)\n",
    "            if n.right:\n",
    "                print_path(n.right)\n",
    "            pth.pop() \n",
    "            if a and b:\n",
    "                return\n",
    "\n",
    "        print_path(root)\n",
    "        if not a or not b:\n",
    "            return None\n",
    "        i, j = 0, 0\n",
    "        while True:\n",
    "            if i >= len(a) or j >= len(b) or a[i].val != b[j].val:\n",
    "                return a[i-1]\n",
    "            else:\n",
    "                i += 1\n",
    "                j += 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':\n",
    "        a, b, pth = [], [], []\n",
    "        def print_path(n):\n",
    "            nonlocal a, b\n",
    "            pth.append(n)\n",
    "            if n.val == p.val:\n",
    "                a = pth.copy()\n",
    "            elif n.val == q.val:\n",
    "                b = pth.copy()\n",
    "\n",
    "            if n.left:\n",
    "                print_path(n.left)\n",
    "            if n.right:\n",
    "                print_path(n.right)\n",
    "            pth.pop() \n",
    "            if a and b:\n",
    "                return\n",
    "\n",
    "        print_path(root)\n",
    "        if not a or not b:\n",
    "            return None\n",
    "        i, j = 0, 0\n",
    "        while True:\n",
    "            if i >= len(a) or j >= len(b) or a[i].val != b[j].val:\n",
    "                return a[i-1]\n",
    "            else:\n",
    "                i += 1\n",
    "                j += 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':\n",
    "        a, b, pth = [], [], []\n",
    "        def print_path(n):  # traverse and print the path in to a and b\n",
    "            nonlocal a, b\n",
    "            pth.append(n)  # keep record of path\n",
    "            if n.val == p.val:\n",
    "                a = pth.copy()\n",
    "            elif n.val == q.val:\n",
    "                b = pth.copy()\n",
    "\n",
    "            if n.left:\n",
    "                print_path(n.left)\n",
    "            if n.right:\n",
    "                print_path(n.right)\n",
    "            pth.pop()\n",
    "            if a and b:  # no need to continue if both found\n",
    "                return\n",
    "\n",
    "        print_path(root)\n",
    "        if not a or not b:  # do not exist\n",
    "            return None\n",
    "        i, j = 0, 0\n",
    "        while i < len(a) and j < len(b):\n",
    "            if a[i].val == b[j].val:\n",
    "                i += 1\n",
    "                j += 1\n",
    "            else:\n",
    "                break\n",
    "        return a[i-1]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':\n",
    "        a, b, pth = [], [], []\n",
    "        def print_path(n):\n",
    "            nonlocal a, b\n",
    "            pth.append(n)\n",
    "            if n.val == p.val:\n",
    "                a = pth.copy()\n",
    "            elif n.val == q.val:\n",
    "                b = pth.copy()\n",
    "\n",
    "            if n.left:\n",
    "                print_path(n.left)\n",
    "            if n.right:\n",
    "                print_path(n.right)\n",
    "            pth.pop() \n",
    "            if a and b:\n",
    "                return\n",
    "\n",
    "        print_path(root)\n",
    "        if not a or not b:\n",
    "            return None\n",
    "        i, j = 0, 0\n",
    "        while True:\n",
    "            if i >= len(a) or j >= len(b) or a[i].val != b[j].val:\n",
    "                return a[i-1]\n",
    "            else:\n",
    "                i += 1\n",
    "                j += 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':\n",
    "        a, b, pth = None, None, []\n",
    "        def print_path(n):\n",
    "            nonlocal a, b\n",
    "            pth.append(n)\n",
    "            if n.val == p.val:\n",
    "                a = pth.copy()\n",
    "            elif n.val == q.val:\n",
    "                b = pth.copy()\n",
    "\n",
    "            if n.left:\n",
    "                print_path(n.left)\n",
    "            if n.right:\n",
    "                print_path(n.right)\n",
    "            aa = pth.pop() \n",
    "            if a and b:\n",
    "                return\n",
    "\n",
    "        print_path(root)\n",
    "        if not a or not b:\n",
    "            return None\n",
    "        i, j = 0, 0\n",
    "        while True:\n",
    "            if i >= len(a) or j >= len(b) or a[i].val != b[j].val:\n",
    "                return a[i-1]\n",
    "            else:\n",
    "                i += 1\n",
    "                j += 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':\n",
    "        a, b, pth = None, None, []\n",
    "        def print_path(n):\n",
    "            nonlocal a, b\n",
    "            pth.append(n)\n",
    "            if n.val == p.val:\n",
    "                a = pth.copy()\n",
    "            elif n.val == q.val:\n",
    "                b = pth.copy()\n",
    "\n",
    "            if n.left:\n",
    "                print_path(n.left)\n",
    "            if n.right:\n",
    "                print_path(n.right)\n",
    "            aa = pth.pop() \n",
    "            if a and b:\n",
    "                return\n",
    "\n",
    "        print_path(root)\n",
    "        if not a or not b:\n",
    "            return None\n",
    "        i, j = 0, 0\n",
    "        while True:\n",
    "            if i >= len(a) or j >= len(b) or a[i].val != b[j].val:\n",
    "                return a[i-1]\n",
    "            else:\n",
    "                i += 1\n",
    "                j += 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':\n",
    "        a, b, pth = None, None, []\n",
    "        def print_path(n):\n",
    "            nonlocal a, b\n",
    "            pth.append(n)\n",
    "            if n.val == p.val:\n",
    "                a = pth.copy()\n",
    "            elif n.val == q.val:\n",
    "                b = pth.copy()\n",
    "\n",
    "            if n.left:\n",
    "                print_path(n.left)\n",
    "            if n.right:\n",
    "                print_path(n.right)\n",
    "            aa = pth.pop() \n",
    "            if a and b:\n",
    "                return\n",
    "\n",
    "        print_path(root)\n",
    "        if not a or not b:\n",
    "            return None\n",
    "        i, j = 0, 0\n",
    "        while True:\n",
    "            if i >= len(a) or j >= len(b) or a[i].val != b[j].val:\n",
    "                return a[i-1]\n",
    "            else:\n",
    "                i += 1\n",
    "                j += 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':\n",
    "        a, b, pth = [], [], []\n",
    "        def print_path(n):  # traverse and print the path in to a and b\n",
    "            nonlocal a, b\n",
    "            pth.append(n)  # keep record of path\n",
    "            if n.val == p.val:\n",
    "                a = pth.copy()\n",
    "            elif n.val == q.val:\n",
    "                b = pth.copy()\n",
    "\n",
    "            if n.left:\n",
    "                print_path(n.left)\n",
    "            if n.right:\n",
    "                print_path(n.right)\n",
    "            pth.pop()\n",
    "            if a and b:  # no need to continue if both found\n",
    "                return\n",
    "\n",
    "        print_path(root)\n",
    "        if not a or not b:  # do not exist\n",
    "            return None\n",
    "        i, j = 0, 0\n",
    "        while i < len(a) and j < len(b):\n",
    "            if a[i].val == b[j].val:\n",
    "                i += 1\n",
    "                j += 1\n",
    "            else:\n",
    "                break\n",
    "        return a[i-1]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':\n",
    "        d=defaultdict()\n",
    "        def dfs(cur,fa):\n",
    "            if cur==None:\n",
    "                return \n",
    "            d[cur]=fa\n",
    "            dfs(cur.left,cur)\n",
    "            dfs(cur.right,cur)\n",
    "        dfs(root,root)\n",
    "        if p not in d or q not in d:\n",
    "            return None\n",
    "        s=set()\n",
    "        s.add(p)\n",
    "        s.add(q)\n",
    "        while p!=root or q!=root:\n",
    "            if p!=root:\n",
    "                p=d[p]\n",
    "                if p in s:\n",
    "                    return p\n",
    "                else:\n",
    "                    s.add(p)\n",
    "            if q!=root:\n",
    "                q=d[q]\n",
    "                if q in s:\n",
    "                    return q\n",
    "                else:\n",
    "                    s.add(q)\n",
    "        return root\n",
    "\n",
    "\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':\n",
    "        fa = {}\n",
    "        def find(x):\n",
    "            if fa[x]!=x:\n",
    "                fa[x] = find(fa[x])\n",
    "            return fa[x]\n",
    "        ans = None\n",
    "        query = {p:q,q:p}\n",
    "        def tarjan(node):\n",
    "            fa[node] = node\n",
    "            for son in node.left,node.right:\n",
    "                if not son:continue\n",
    "                if tarjan(son):return True\n",
    "                fa[son] = node\n",
    "            if node in query and query[node] in fa:\n",
    "                nonlocal ans\n",
    "                ans =  find(query[node])\n",
    "                return True\n",
    "        tarjan(root)\n",
    "        return ans\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val):\n",
    "        self.val = val\n",
    "        self.left = None\n",
    "        self.right = None\n",
    "        self.parent = None\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, p: 'Node', q: 'Node') -> 'Node':\n",
    "        p1, p2 = p, q\n",
    "        while p1 != p2:\n",
    "            p1 = p1.parent if p1.parent else q\n",
    "            p2 = p2.parent if p2.parent else p\n",
    "        return p1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val):\n",
    "        self.val = val\n",
    "        self.left = None\n",
    "        self.right = None\n",
    "        self.parent = None\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, p: 'Node', q: 'Node') -> 'Node':\n",
    "        # parent pointer\n",
    "        # O(n) O(n)\n",
    "        visited = set()\n",
    "        while p or q:\n",
    "            if p:\n",
    "                if p in visited:\n",
    "                    return p\n",
    "                else:\n",
    "                    visited.add(p)\n",
    "                    p = p.parent\n",
    "            if q:\n",
    "                if q in visited:\n",
    "                    return q\n",
    "                else:\n",
    "                    visited.add(q)\n",
    "                    q = q.parent\n",
    "\n",
    "        # O(n) O(1) space complexity\n",
    "        # linked list \n",
    "        # a, b = p, q\n",
    "        # while a is not b:\n",
    "        #     a = p if a == None else a.parent\n",
    "        #     b = q if b == None else b.parent\n",
    "        # return a\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val):\n",
    "        self.val = val\n",
    "        self.left = None\n",
    "        self.right = None\n",
    "        self.parent = None\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, p: 'Node', q: 'Node') -> 'Node':\n",
    "        a = p\n",
    "        b = q\n",
    "        while a != b:\n",
    "            if a:\n",
    "                a = a.parent\n",
    "            else:\n",
    "                a = q\n",
    "            if b:\n",
    "                b = b.parent\n",
    "            else:\n",
    "                b = p\n",
    "        return a"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val):\n",
    "        self.val = val\n",
    "        self.left = None\n",
    "        self.right = None\n",
    "        self.parent = None\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, p: 'Node', q: 'Node') -> 'Node':\n",
    "        p1 = p\n",
    "        p2 = q\n",
    "        while p1 != p2:\n",
    "            p1 = p1.parent if p1.parent else q\n",
    "            p2 = p2.parent if p2.parent else p\n",
    "        return p1\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val):\n",
    "        self.val = val\n",
    "        self.left = None\n",
    "        self.right = None\n",
    "        self.parent = None\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, p: 'Node', q: 'Node') -> 'Node':\n",
    "        # 使用链表双指针技巧\n",
    "        a, b = p, q\n",
    "        while a != b:\n",
    "            # a 走一步，如果走到根节点，转到 q 节点\n",
    "            if a is None:\n",
    "                a = q\n",
    "            else:\n",
    "                a = a.parent\n",
    "            # b 走一步，如果走到根节点，转到 p 节点\n",
    "            if b is None:\n",
    "                b = p\n",
    "            else:\n",
    "                b = b.parent\n",
    "        return a"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val):\n",
    "        self.val = val\n",
    "        self.left = None\n",
    "        self.right = None\n",
    "        self.parent = None\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, p: 'Node', q: 'Node') -> 'Node':\n",
    "        a, b = p, q \n",
    "\n",
    "        while a != b: \n",
    "            if a is None:\n",
    "                a = q \n",
    "            else: \n",
    "                a = a.parent \n",
    "\n",
    "            if b is None:\n",
    "                b = p\n",
    "            else:\n",
    "                b = b.parent\n",
    "\n",
    "        return a"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val):\n",
    "        self.val = val\n",
    "        self.left = None\n",
    "        self.right = None\n",
    "        self.parent = None\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, p: 'Node', q: 'Node') -> 'Node':\n",
    "        seen = set()\n",
    "        queue = deque([p, q])\n",
    "\n",
    "        while queue:\n",
    "            curr = queue.popleft()\n",
    "\n",
    "            if curr in seen:\n",
    "                return curr\n",
    "            seen.add(curr)\n",
    "            if curr.parent is not None:\n",
    "                queue.append(curr.parent)\n",
    "        return None"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val):\n",
    "        self.val = val\n",
    "        self.left = None\n",
    "        self.right = None\n",
    "        self.parent = None\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, p: 'Node', q: 'Node') -> 'Node':\n",
    "        a = p \n",
    "        b = q\n",
    "        while a != b:\n",
    "            if a.parent:\n",
    "                a = a.parent\n",
    "            else:\n",
    "                a = q\n",
    "            if b.parent:\n",
    "                b = b.parent\n",
    "            else:\n",
    "                b = p\n",
    "        return a"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val):\n",
    "        self.val = val\n",
    "        self.left = None\n",
    "        self.right = None\n",
    "        self.parent = None\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, p: 'Node', q: 'Node') -> 'Node':\n",
    "        visited = set()\n",
    "        queue = collections.deque([p,q])\n",
    "  \n",
    "        while queue:\n",
    "            cur = queue.popleft()\n",
    "            if cur in visited:\n",
    "                return cur \n",
    "            visited.add(cur)\n",
    "            if cur.parent:\n",
    "                queue.append(cur.parent)\n",
    "\n",
    "            "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val):\n",
    "        self.val = val\n",
    "        self.left = None\n",
    "        self.right = None\n",
    "        self.parent = None\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, p: 'Node', q: 'Node') -> 'Node':\n",
    "        n_set = set()\n",
    "\n",
    "        while p or q:\n",
    "            if p:\n",
    "                if p in n_set:  \n",
    "                    return p\n",
    "                n_set.add(p)\n",
    "                p = p.parent\n",
    "                \n",
    "            if q:\n",
    "                if q in n_set:\n",
    "                    return q\n",
    "                n_set.add(q)\n",
    "                q = q.parent\n",
    "        \n",
    "        return None\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val):\n",
    "        self.val = val\n",
    "        self.left = None\n",
    "        self.right = None\n",
    "        self.parent = None\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, p: 'Node', q: 'Node') -> 'Node':\n",
    "        d = set()\n",
    "        deque = collections.deque([p, q])\n",
    "        while deque:\n",
    "            cur = deque.popleft()\n",
    "            if cur in d:\n",
    "                return cur\n",
    "            d.add(cur)\n",
    "            if cur.parent:\n",
    "                deque.append(cur.parent)\n",
    "        return \n",
    "\n",
    "\n",
    "\n",
    "        # d = set()\n",
    "        # cur = p\n",
    "        # while cur:\n",
    "        #     d.add(cur)\n",
    "        #     cur = cur.parent\n",
    "        # cur = q \n",
    "        # while cur:\n",
    "        #     if cur in d:\n",
    "        #         return cur\n",
    "        #     cur = cur.parent\n",
    "        \n",
    "\n",
    "\n",
    "\n",
    "\n",
    "        # seen = set()\n",
    "        # queue = collections.deque([p, q])\n",
    "        # while queue:\n",
    "        #     cur = queue.popleft()\n",
    "        #     if cur in seen:\n",
    "        #         return cur\n",
    "        #     seen.add(cur)\n",
    "        #     if cur.parent:\n",
    "        #         queue.append(cur.parent)\n",
    "        \n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val):\n",
    "        self.val = val\n",
    "        self.left = None\n",
    "        self.right = None\n",
    "        self.parent = None\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, p: 'Node', q: 'Node') -> 'Node':\n",
    "        a, b = p, q\n",
    "        while a != b:\n",
    "            a = a.parent if a.parent else q\n",
    "            b = b.parent if b.parent else p\n",
    "        return a\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val):\n",
    "        self.val = val\n",
    "        self.left = None\n",
    "        self.right = None\n",
    "        self.parent = None\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, p: 'Node', q: 'Node') -> 'Node':\n",
    "        memo={}\n",
    "        def iscommon(tree,q):\n",
    "            nonlocal memo\n",
    "            if tree in memo:\n",
    "                return memo[tree]\n",
    "            if tree==None:\n",
    "                return False\n",
    "            \n",
    "            mid,left,right=False,False,False\n",
    "            if tree==q:\n",
    "                mid=True\n",
    "            left=iscommon(tree.left,q)\n",
    "            right=iscommon(tree.right,q)\n",
    "\n",
    "            memo[tree]= (mid or left or right)\n",
    "\n",
    "            return memo[tree]\n",
    "\n",
    "\n",
    "            \n",
    "\n",
    "        parents=[]\n",
    "\n",
    "        pointer=p\n",
    "\n",
    "        while pointer!=None:\n",
    "            parents.append(pointer)\n",
    "            pointer=pointer.parent\n",
    "        \n",
    "        for node in parents:\n",
    "            if iscommon(node,q):\n",
    "                return node\n",
    "                \n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val):\n",
    "        self.val = val\n",
    "        self.left = None\n",
    "        self.right = None\n",
    "        self.parent = None\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, p: 'Node', q: 'Node') -> 'Node':\n",
    "        node1 = p\n",
    "        node2 = q\n",
    "        while node1 != node2:\n",
    "            if node1.parent:\n",
    "                node1 = node1.parent\n",
    "            else:\n",
    "                node1 = q\n",
    "            if node2.parent:\n",
    "                node2 = node2.parent\n",
    "            else:\n",
    "                node2 = p\n",
    "        \n",
    "        return node1\n",
    "\n",
    "'''\n",
    "p:\n",
    "5 -> 3\n",
    "1 -> 3\n",
    "linkedList\n",
    "\n",
    "LCA is the first common nodes\n",
    "\n",
    "m + p + n\n",
    "n + p + m\n",
    "\n",
    "node1 = p\n",
    "node2 = q\n",
    "while node1 != node2:\n",
    "    if node1.parent:\n",
    "        node1 = node1.parent\n",
    "    else:\n",
    "        node1 = q\n",
    "    if node2.parent:\n",
    "        node2 = node2.parent\n",
    "    else:\n",
    "        node2 = p\n",
    "\n",
    "LCA is node1 \n",
    "\n",
    "step0\n",
    "node1 = 5\n",
    "node2 = 5\n",
    "step1\n",
    "node1 = 3\n",
    "node2 = 2\n",
    "step2\n",
    "node1 = 4\n",
    "node2 = 5\n",
    "step3\n",
    "node1 = 2\n",
    "node2 = 3\n",
    "step4\n",
    "node1 = 5\n",
    "node2 = 5\n",
    "\n",
    "\n",
    "'''\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val):\n",
    "        self.val = val\n",
    "        self.left = None\n",
    "        self.right = None\n",
    "        self.parent = None\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, p: 'Node', q: 'Node') -> 'Node':\n",
    "        ##找两链表相交节点\n",
    "        a = p\n",
    "        b = q\n",
    "        while a != b:\n",
    "            if a:\n",
    "                a = a.parent\n",
    "            else:\n",
    "                a = q\n",
    "            if b:\n",
    "                b = b.parent\n",
    "            else:\n",
    "                b = p\n",
    "        return a \n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val):\n",
    "        self.val = val\n",
    "        self.left = None\n",
    "        self.right = None\n",
    "        self.parent = None\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, p: 'Node', q: 'Node') -> 'Node':\n",
    "        p_cur = p\n",
    "        q_cur = q\n",
    "        while p_cur != q_cur:\n",
    "            if p_cur.parent:\n",
    "                p_cur = p_cur.parent\n",
    "            else:\n",
    "                p_cur = q\n",
    "            if q_cur.parent:\n",
    "                q_cur = q_cur.parent\n",
    "            else:\n",
    "                q_cur = p\n",
    "        return p_cur"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val):\n",
    "        self.val = val\n",
    "        self.left = None\n",
    "        self.right = None\n",
    "        self.parent = None\n",
    "\"\"\"\n",
    "from collections import defaultdict, deque\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, p: 'Node', q: 'Node') -> 'Node':\n",
    "        nodes = defaultdict(int)\n",
    "        # nodes = set()\n",
    "        queue = deque([p, q])\n",
    "        while queue:\n",
    "            current = queue.popleft()\n",
    "            # if current in nodes: return current\n",
    "            # nodes.add(current)\n",
    "            if current in nodes.keys(): return current\n",
    "            nodes[current] = 1\n",
    "            if current.parent:\n",
    "                queue.append(current.parent)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val):\n",
    "        self.val = val\n",
    "        self.left = None\n",
    "        self.right = None\n",
    "        self.parent = None\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, p: 'Node', q: 'Node') -> 'Node':\n",
    "        pDepth = qDepth = 0\n",
    "        pNode, qNode = p, q\n",
    "        while pNode.parent:\n",
    "            pNode = pNode.parent\n",
    "            pDepth += 1\n",
    "        while qNode.parent:\n",
    "            qNode = qNode.parent\n",
    "            qDepth += 1\n",
    "        if pDepth > qDepth: \n",
    "            for i in range(pDepth - qDepth):\n",
    "                p = p.parent\n",
    "        else:\n",
    "            for i in range(qDepth-pDepth):\n",
    "                q = q.parent\n",
    "        while p != q:\n",
    "            p = p.parent\n",
    "            q = q.parent\n",
    "        return p\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val):\n",
    "        self.val = val\n",
    "        self.left = None\n",
    "        self.right = None\n",
    "        self.parent = None\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, p: 'Node', q: 'Node') -> 'Node':\n",
    "        hp = p\n",
    "        hq = q\n",
    "        while hp!=hq:\n",
    "            hp = hp.parent if hp.parent else q\n",
    "            hq = hq.parent if hq.parent else p\n",
    "\n",
    "        return hp\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val):\n",
    "        self.val = val\n",
    "        self.left = None\n",
    "        self.right = None\n",
    "        self.parent = None\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, p: 'Node', q: 'Node') -> 'Node':\n",
    "        dp,dq = p,q\n",
    "        while dp.val!=dq.val:\n",
    "            dp = dp.parent if dp.parent else q\n",
    "            dq = dq.parent if dq.parent else p\n",
    "        return dp\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val):\n",
    "        self.val = val\n",
    "        self.left = None\n",
    "        self.right = None\n",
    "        self.parent = None\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, p: 'Node', q: 'Node') -> 'Node':\n",
    "        # 由于每个节点存在指向父节点的指针，所以等价于链表相交题\n",
    "        p1, p2=p, q\n",
    "        while p1 != p2:\n",
    "            if p1 is None: p1 = q\n",
    "            else: p1 = p1.parent\n",
    "            if p2 is None: p2 = p\n",
    "            else: p2 = p2.parent\n",
    "        return p1\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val):\n",
    "        self.val = val\n",
    "        self.left = None\n",
    "        self.right = None\n",
    "        self.parent = None\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, p: 'Node', q: 'Node') -> 'Node':\n",
    "        fast = p\n",
    "        slow = q\n",
    "\n",
    "        while fast != slow:\n",
    "\n",
    "            if not fast:\n",
    "                fast = q\n",
    "            else:\n",
    "                fast = fast.parent\n",
    "            \n",
    "            if not slow:\n",
    "                slow = p\n",
    "            else:\n",
    "                slow = slow.parent\n",
    "\n",
    "        return fast\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val):\n",
    "        self.val = val\n",
    "        self.left = None\n",
    "        self.right = None\n",
    "        self.parent = None\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, p: 'Node', q: 'Node') -> 'Node':\n",
    "        p_parents = []\n",
    "        q_parents = []\n",
    "        cur = p\n",
    "        while cur:\n",
    "            p_parents.append(cur)\n",
    "            cur = cur.parent\n",
    "        cur = q\n",
    "        while cur:\n",
    "            q_parents.append(cur)\n",
    "            cur = cur.parent\n",
    "        p_parents = p_parents[::-1]\n",
    "        q_parents = q_parents[::-1]\n",
    "        res = None\n",
    "        n = min(len(p_parents), len(q_parents))\n",
    "        for i in range(n):\n",
    "            if p_parents[i] == q_parents[i]:\n",
    "                res = p_parents[i]\n",
    "            else:\n",
    "                break\n",
    "        return res\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val):\n",
    "        self.val = val\n",
    "        self.left = None\n",
    "        self.right = None\n",
    "        self.parent = None\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, p: 'Node', q: 'Node') -> 'Node':\n",
    "        pSet, qSet = set(), set()\n",
    "        while p or q:\n",
    "            if pSet & qSet:\n",
    "                return (pSet & qSet).pop()\n",
    "            if p: pSet.add(p)\n",
    "            if q: qSet.add(q)\n",
    "            if p.parent: p = p.parent\n",
    "            if q.parent: q = q.parent\n",
    "            \n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val):\n",
    "        self.val = val\n",
    "        self.left = None\n",
    "        self.right = None\n",
    "        self.parent = None\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, p: 'Node', q: 'Node') -> 'Node':\n",
    "        pDir, qDir = [], []\n",
    "        while p:\n",
    "            if p.parent:\n",
    "                if p is p.parent.left:\n",
    "                    pDir.append(0)\n",
    "                else:\n",
    "                    pDir.append(1)\n",
    "            p = p.parent\n",
    "\n",
    "        root = None\n",
    "        while q:\n",
    "            if q.parent:\n",
    "                if q is q.parent.left:\n",
    "                    qDir.append(0)\n",
    "                else:\n",
    "                    qDir.append(1)\n",
    "            root = q\n",
    "            q = q.parent\n",
    "\n",
    "\n",
    "\n",
    "        pDir = pDir[::-1]\n",
    "        qDir =qDir[::-1]\n",
    "\n",
    "        print(\"-----\")\n",
    "        print(\"pDir: \", pDir)\n",
    "        print(\"qDir: \", qDir)\n",
    "\n",
    "        step = 0\n",
    "        lastCommonAnc = root\n",
    "        while step < len(pDir) and step < len(qDir):\n",
    "            if pDir[step] == qDir[step]:\n",
    "                lastCommonAnc = lastCommonAnc.left if pDir[step] == 0 else lastCommonAnc.right\n",
    "                step += 1\n",
    "            else:\n",
    "                return lastCommonAnc\n",
    "        return lastCommonAnc\n",
    "\n",
    "\n",
    "\n",
    "        \n",
    "\n",
    "\n",
    "\n",
    "            \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val):\n",
    "        self.val = val\n",
    "        self.left = None\n",
    "        self.right = None\n",
    "        self.parent = None\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, p: 'Node', q: 'Node') -> 'Node':\n",
    "        keep = []\n",
    "        cur = p\n",
    "        while cur:\n",
    "            keep.append(cur.val)\n",
    "            cur = cur.parent\n",
    "\n",
    "        cur2 = q\n",
    "        while cur2:\n",
    "            if cur2.val in keep:\n",
    "                return cur2\n",
    "            else:\n",
    "                cur2 = cur2.parent\n",
    "\n",
    "        return "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val):\n",
    "        self.val = val\n",
    "        self.left = None\n",
    "        self.right = None\n",
    "        self.parent = None\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, p: 'Node', q: 'Node') -> 'Node':\n",
    "        \n",
    "        def find_length(node):\n",
    "            n1 = 0\n",
    "            while node:\n",
    "                n1 += 1\n",
    "                node = node.parent\n",
    "            return n1\n",
    "        \n",
    "        node = p\n",
    "        n1 = find_length(node)\n",
    "        node = q\n",
    "        n2 = find_length(node)\n",
    "        \n",
    "        while n1 > n2:\n",
    "            p = p.parent\n",
    "            n1 -= 1\n",
    "        \n",
    "        while n2 > n1:\n",
    "            q = q.parent\n",
    "            n2 -= 1\n",
    "\n",
    "        while n1 >= 0:\n",
    "            if q == p:\n",
    "                return q\n",
    "            else:\n",
    "                q = q.parent\n",
    "                p = p.parent\n",
    "            n1 -= 1\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val):\n",
    "        self.val = val\n",
    "        self.left = None\n",
    "        self.right = None\n",
    "        self.parent = None\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, p: 'Node', q: 'Node') -> 'Node':\n",
    "        p_cur = p\n",
    "        q_cur = q\n",
    "        while p_cur != q_cur:\n",
    "            if p_cur.parent:\n",
    "                p_cur = p_cur.parent\n",
    "            else:\n",
    "                p_cur = q\n",
    "            if q_cur.parent:\n",
    "                q_cur = q_cur.parent\n",
    "            else:\n",
    "                q_cur = p\n",
    "        return p_cur"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val):\n",
    "        self.val = val\n",
    "        self.left = None\n",
    "        self.right = None\n",
    "        self.parent = None\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, p: 'Node', q: 'Node') -> 'Node':\n",
    "        keep = set()\n",
    "        cur1, cur2 = p, q \n",
    "        while cur1 or cur2:\n",
    "            if cur1:\n",
    "                if cur1.val in keep:\n",
    "                    return cur1\n",
    "                else:\n",
    "                    keep.add(cur1.val)\n",
    "                    cur1 = cur1.parent\n",
    "\n",
    "            if cur2:\n",
    "                if cur2.val in keep:\n",
    "                    return cur2\n",
    "                else:\n",
    "                    keep.add(cur2.val)\n",
    "                    cur2 = cur2.parent\n",
    "\n",
    "        return "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val):\n",
    "        self.val = val\n",
    "        self.left = None\n",
    "        self.right = None\n",
    "        self.parent = None\n",
    "\"\"\"\n",
    "from collections import defaultdict, deque\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, p: 'Node', q: 'Node') -> 'Node':\n",
    "        # nodes = defaultdict(int)\n",
    "        nodes = set()\n",
    "        queue = deque([p, q])\n",
    "        while queue:\n",
    "            current = queue.popleft()\n",
    "            # if current in nodes.keys(): return current\n",
    "            # nodes[current] = 1\n",
    "            if current in nodes: return current\n",
    "            nodes.add(current)\n",
    "            if current.parent:\n",
    "                queue.append(current.parent)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val):\n",
    "        self.val = val\n",
    "        self.left = None\n",
    "        self.right = None\n",
    "        self.parent = None\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, p: 'Node', q: 'Node') -> 'Node':\n",
    "        p_start, q_start = p, q\n",
    "        \n",
    "        while p != q:\n",
    "            p = p.parent if p.parent else q_start\n",
    "            q = q.parent if q.parent else p_start\n",
    "        \n",
    "        return p"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val):\n",
    "        self.val = val\n",
    "        self.left = None\n",
    "        self.right = None\n",
    "        self.parent = None\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, p: 'Node', q: 'Node') -> 'Node':\n",
    "        seen = set()\n",
    "        queue = collections.deque([p, q])\n",
    "        while queue:\n",
    "            cur = queue.popleft()\n",
    "            if cur in seen:\n",
    "                return cur\n",
    "            seen.add(cur)\n",
    "            if cur.parent:\n",
    "                queue.append(cur.parent)\n",
    "        \n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution(object):\n",
    "    def lowestCommonAncestor(self, p, q):\n",
    "        \"\"\"\n",
    "        :type node: Node\n",
    "        :rtype: Node\n",
    "        \"\"\"\n",
    "        d = {}\n",
    "        left = p\n",
    "        right = q\n",
    "        while left or right:\n",
    "            if left:\n",
    "                if not left in d.keys():\n",
    "                    d[left] = 1\n",
    "                    left = left.parent\n",
    "                else:\n",
    "                    return left\n",
    "\n",
    "            if right:\n",
    "                if not right in d.keys():\n",
    "                    d[right] = 1\n",
    "                    right = right.parent\n",
    "                else:\n",
    "                    return right\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val):\n",
    "        self.val = val\n",
    "        self.left = None\n",
    "        self.right = None\n",
    "        self.parent = None\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, p: 'Node', q: 'Node') -> 'Node':\n",
    "        pointer1 = p\n",
    "        pointer2 = q\n",
    "\n",
    "        while pointer1 != pointer2:\n",
    "            if pointer1.parent:\n",
    "                pointer1 = pointer1.parent\n",
    "            else:\n",
    "                pointer1 = q\n",
    "            \n",
    "            if pointer2.parent:\n",
    "                pointer2 = pointer2.parent\n",
    "            else:\n",
    "                pointer2 = p\n",
    "        \n",
    "        return pointer1\n",
    "        \n",
    "        \n",
    "\n",
    "        self.ans = root\n",
    "\n",
    "        def _DFS(root, p, q):\n",
    "            if root == p:\n",
    "                self.ans = p\n",
    "                return True\n",
    "            if root == q:\n",
    "                self.ans = q\n",
    "                return True\n",
    "\n",
    "            leftFlag = False\n",
    "            if root.left:\n",
    "                leftFlag = _DFS(root.left, p, q)\n",
    "            rightFlag = False\n",
    "            if root.right:\n",
    "                rightFlag = _DFS(root.right, p, q)\n",
    "\n",
    "            if leftFlag and rightFlag:\n",
    "                self.ans = root\n",
    "            return leftFlag or rightFlag\n",
    "        \n",
    "        _DFS(root, p, q)\n",
    "\n",
    "        return self.ans\n",
    "                        \n",
    "'''\n",
    "DFS(root, p, q)\n",
    "    if root == p or root == q:\n",
    "        ans = p or q\n",
    "        return True\n",
    "\n",
    "    leftFlag = DFS(root.left, p, q)\n",
    "    rightFlag = DFS(root.right, p, q)\n",
    "\n",
    "    if leftFlag and rightFlag:\n",
    "        ans  = root\n",
    "        return True\n",
    "    \n",
    "    return leftFlag or rightFlag\n",
    "\n",
    "'''\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val):\n",
    "        self.val = val\n",
    "        self.left = None\n",
    "        self.right = None\n",
    "        self.parent = None\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, p: 'Node', q: 'Node') -> 'Node':\n",
    "        path_p = self.pathToRoot(p)\n",
    "        path_q = self.pathToRoot(q)\n",
    "        \n",
    "        i = len(path_p) - 1\n",
    "        j = len(path_q) - 1\n",
    "        \n",
    "        while i >= 0 and j >= 0 and path_p[i] == path_q[j]:\n",
    "            i -= 1\n",
    "            j -= 1\n",
    "        \n",
    "        return path_p[i + 1]\n",
    "    \n",
    "    def pathToRoot(self, node):\n",
    "        path = []\n",
    "        while node:\n",
    "            path.append(node)\n",
    "            node = node.parent\n",
    "        return path"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val):\n",
    "        self.val = val\n",
    "        self.left = None\n",
    "        self.right = None\n",
    "        self.parent = None\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, p: 'Node', q: 'Node') -> 'Node':\n",
    "        \"\"\" no root input compare with No.236 \n",
    "        apply recursion bottom up \n",
    "        \"\"\"\n",
    "        def dfs(p, q, hashmap):\n",
    "            \"\"\"bottom up tracking up to the root\"\"\"\n",
    "            if p == q:\n",
    "                return p  # recursion termination criteria\n",
    "            # logic at one level \n",
    "            if p.parent and p in hashmap: # P.PARENT MUST\n",
    "                return p \n",
    "            else:\n",
    "                hashmap.add(p)\n",
    "            if q.parent and q in hashmap:\n",
    "                return q\n",
    "            else:\n",
    "                hashmap.add(q)\n",
    "            # return the node traversal from bottom to top which has been added to the hashmap and \n",
    "            # seen by the other node again \n",
    "            return dfs(p.parent if p.parent else p, q.parent if q.parent else q, hashmap)\n",
    "\n",
    "        hashmap = set()\n",
    "        # apply recursion \n",
    "        ans = dfs(p, q, hashmap)\n",
    "        return ans\n",
    "\n",
    "# 作者：清濑灰二\n",
    "# 链接：https://leetcode.cn/problems/lowest-common-ancestor-of-a-binary-tree-iii/solutions/1537786/y-by-lc-producer-ugfx/\n",
    "# 来源：力扣（LeetCode）\n",
    "# 著作权归作者所有。商业转载请联系作者获得授权，非商业转载请注明出处。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution(object):\n",
    "    def lowestCommonAncestor(self, p, q):\n",
    "        \"\"\"\n",
    "        :type node: Node\n",
    "        :rtype: Node\n",
    "        \"\"\"\n",
    "        d = {}\n",
    "        left = p\n",
    "        right = q\n",
    "        while left or right:\n",
    "            if left:\n",
    "                if not left in d.keys():\n",
    "                    d[left] = 1\n",
    "                    left = left.parent\n",
    "                else:\n",
    "                    return left\n",
    "\n",
    "            if right:\n",
    "                if not right in d.keys():\n",
    "                    d[right] = 1\n",
    "                    right = right.parent\n",
    "                else:\n",
    "                    return right\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val):\n",
    "        self.val = val\n",
    "        self.left = None\n",
    "        self.right = None\n",
    "        self.parent = None\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, p: 'Node', q: 'Node') -> 'Node':\n",
    "        a, b = p, q\n",
    "        while a != b:\n",
    "            if not a:\n",
    "                a = q\n",
    "            else:\n",
    "                a = a.parent\n",
    "            \n",
    "            if not b:\n",
    "                b = p\n",
    "            else:\n",
    "                b = b.parent\n",
    "        return a "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution(object):\n",
    "    def lowestCommonAncestor(self, p, q):\n",
    "        \"\"\"\n",
    "        :type node: Node\n",
    "        :rtype: Node\n",
    "        \"\"\"\n",
    "        d = {}\n",
    "        left = p\n",
    "        right = q\n",
    "        while left or right:\n",
    "            if left:\n",
    "                if not left in d.keys():\n",
    "                    d[left] = 1\n",
    "                    left = left.parent\n",
    "                else:\n",
    "                    return left\n",
    "\n",
    "            if right:\n",
    "                if not right in d.keys():\n",
    "                    d[right] = 1\n",
    "                    right = right.parent\n",
    "                else:\n",
    "                    return right\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val):\n",
    "        self.val = val\n",
    "        self.left = None\n",
    "        self.right = None\n",
    "        self.parent = None\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, p: 'Node', q: 'Node') -> 'Node':\n",
    "        # 施展链表双指针技巧\n",
    "        a, b = p, q\n",
    "        while a != b:\n",
    "            # a 走一步，如果走到根节点，转到 q 节点\n",
    "            a = a.parent if a.parent else q\n",
    "            # b 走一步，如果走到根节点，转到 p 节点\n",
    "            b = b.parent if b.parent else p\n",
    "        # 最后2个节点的相遇点，就是2个节点的公共祖先\n",
    "        return a"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val):\n",
    "        self.val = val\n",
    "        self.left = None\n",
    "        self.right = None\n",
    "        self.parent = None\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, p: 'Node', q: 'Node') -> 'Node':\n",
    "        def lowest_common(p: 'Node', q: 'Node', p_ancestors: list('Node'), q_ancestors: list('Node')):\n",
    "            if q in p_ancestors:\n",
    "                return q\n",
    "            if p in q_ancestors:\n",
    "                return p\n",
    "            if not p and not q:\n",
    "                return p.intersection(q)[0]\n",
    "            if not p:\n",
    "                q_ancestors.add(q)\n",
    "                return lowest_common(p, q.parent, p_ancestors, q_ancestors)\n",
    "            if not q:\n",
    "                p_ancestors.add(p)\n",
    "                return lowest_common(p.parent, q, p_ancestors, q_ancestors)\n",
    "            if q == p:\n",
    "                return p\n",
    "            p_ancestors.add(p)\n",
    "            q_ancestors.add(q)\n",
    "            return lowest_common(p.parent, q.parent, p_ancestors, q_ancestors)\n",
    "        return lowest_common(p, q, set(), set())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val):\n",
    "        self.val = val\n",
    "        self.left = None\n",
    "        self.right = None\n",
    "        self.parent = None\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, p: 'Node', q: 'Node') -> 'Node':\n",
    "        left = p\n",
    "        right = q\n",
    "        # two pointer problem\n",
    "        while left != right:\n",
    "            left = left.parent if left.parent else q # if hit root, go to the other node\n",
    "            right = right.parent if right.parent else p\n",
    "        return left"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution(object):\n",
    "    def lowestCommonAncestor(self, p, q):\n",
    "        \"\"\"\n",
    "        :type node: Node\n",
    "        :rtype: Node\n",
    "        \"\"\"\n",
    "        d = {}\n",
    "        left = p\n",
    "        right = q\n",
    "        while left or right:\n",
    "            if left:\n",
    "                if not left in d.keys():\n",
    "                    d[left] = 1\n",
    "                    left = left.parent\n",
    "                else:\n",
    "                    return left\n",
    "\n",
    "            if right:\n",
    "                if not right in d.keys():\n",
    "                    d[right] = 1\n",
    "                    right = right.parent\n",
    "                else:\n",
    "                    return right\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val):\n",
    "        self.val = val\n",
    "        self.left = None\n",
    "        self.right = None\n",
    "        self.parent = None\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, p: 'Node', q: 'Node') -> 'Node':\n",
    "        a, b = p, q\n",
    "        while a != b:\n",
    "            a = a.parent if a.parent else q  # .parent q\n",
    "            b = b.parent if b.parent else p # .parent p\n",
    "        return a"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution(object):\n",
    "    def lowestCommonAncestor(self, p, q):\n",
    "        \"\"\"\n",
    "        :type node: Node\n",
    "        :rtype: Node\n",
    "        \"\"\"\n",
    "        d = {}\n",
    "        left = p\n",
    "        right = q\n",
    "        while left or right:\n",
    "            if left:\n",
    "                if not left in d.keys():\n",
    "                    d[left] = 1\n",
    "                    left = left.parent\n",
    "                else:\n",
    "                    return left\n",
    "\n",
    "            if right:\n",
    "                if not right in d.keys():\n",
    "                    d[right] = 1\n",
    "                    right = right.parent\n",
    "                else:\n",
    "                    return right\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val):\n",
    "        self.val = val\n",
    "        self.left = None\n",
    "        self.right = None\n",
    "        self.parent = None\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, p: 'Node', q: 'Node') -> 'Node':\n",
    "        print('new case', p.val, q.val)\n",
    "        keep = []\n",
    "        cur = p\n",
    "        while cur:\n",
    "            keep.append(cur.val)\n",
    "            cur = cur.parent\n",
    "\n",
    "        cur2 = q\n",
    "        while cur2:\n",
    "            if cur2.val in keep:\n",
    "                return cur2\n",
    "            else:\n",
    "                cur2 = cur2.parent\n",
    "\n",
    "        return "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution(object):\n",
    "    def lowestCommonAncestor(self, p, q):\n",
    "        \"\"\"\n",
    "        :type node: Node\n",
    "        :rtype: Node\n",
    "        \"\"\"\n",
    "        d = {}\n",
    "        left = p\n",
    "        right = q\n",
    "        while left or right:\n",
    "            if left:\n",
    "                if not left in d.keys():\n",
    "                    d[left] = 1\n",
    "                    left = left.parent\n",
    "                else:\n",
    "                    return left\n",
    "\n",
    "            if right:\n",
    "                if not right in d.keys():\n",
    "                    d[right] = 1\n",
    "                    right = right.parent\n",
    "                else:\n",
    "                    return right\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val):\n",
    "        self.val = val\n",
    "        self.left = None\n",
    "        self.right = None\n",
    "        self.parent = None\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, p: 'Node', q: 'Node') -> 'Node':\n",
    "        path_p = [p]\n",
    "        path_q = [q]\n",
    "\n",
    "        for que in [path_p, path_q]:\n",
    "            while que[-1]:\n",
    "                last_n = que[-1]\n",
    "                que.append(last_n.parent)\n",
    "        \n",
    "        path_p = path_p[::-1]\n",
    "        path_q = path_q[::-1]\n",
    "\n",
    "        last_n = None\n",
    "        max_l = min(len(path_p), len(path_q))\n",
    "\n",
    "        # print(path_p, path_q)\n",
    "\n",
    "        for i in range(max_l):\n",
    "            if path_p[i] == path_q[i]:\n",
    "                last_n = path_p[i]\n",
    "            else:\n",
    "                break\n",
    "        \n",
    "        return last_n\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution(object):\n",
    "    def lowestCommonAncestor(self, p, q):\n",
    "        \"\"\"\n",
    "        :type node: Node\n",
    "        :rtype: Node\n",
    "        \"\"\"\n",
    "        d = {}\n",
    "        left = p\n",
    "        right = q\n",
    "        while left or right:\n",
    "            if left:\n",
    "                if not left in d.keys():\n",
    "                    d[left] = 1\n",
    "                    left = left.parent\n",
    "                else:\n",
    "                    return left\n",
    "\n",
    "            if right:\n",
    "                if not right in d.keys():\n",
    "                    d[right] = 1\n",
    "                    right = right.parent\n",
    "                else:\n",
    "                    return right\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution(object):\n",
    "    def lowestCommonAncestor(self, p, q):\n",
    "        \"\"\"\n",
    "        :type node: Node\n",
    "        :rtype: Node\n",
    "        \"\"\"\n",
    "        d = {}\n",
    "        left = p\n",
    "        right = q\n",
    "        while left or right:\n",
    "            if left:\n",
    "                if not left in d.keys():\n",
    "                    d[left] = 1\n",
    "                    left = left.parent\n",
    "                else:\n",
    "                    return left\n",
    "\n",
    "            if right:\n",
    "                if not right in d.keys():\n",
    "                    d[right] = 1\n",
    "                    right = right.parent\n",
    "                else:\n",
    "                    return right\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution(object):\n",
    "    def lowestCommonAncestor(self, p, q):\n",
    "        \"\"\"\n",
    "        :type node: Node\n",
    "        :rtype: Node\n",
    "        \"\"\"\n",
    "        d = {}\n",
    "        left = p\n",
    "        right = q\n",
    "        while left or right:\n",
    "            if left:\n",
    "                if not left in d.keys():\n",
    "                    d[left] = 1\n",
    "                    left = left.parent\n",
    "                else:\n",
    "                    return left\n",
    "\n",
    "            if right:\n",
    "                if not right in d.keys():\n",
    "                    d[right] = 1\n",
    "                    right = right.parent\n",
    "                else:\n",
    "                    return right\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution(object):\n",
    "    def lowestCommonAncestor(self, p, q):\n",
    "        \"\"\"\n",
    "        :type node: Node\n",
    "        :rtype: Node\n",
    "        \"\"\"\n",
    "        d = {}\n",
    "        left = p\n",
    "        right = q\n",
    "        while left or right:\n",
    "            if left:\n",
    "                if not left in d.keys():\n",
    "                    d[left] = 1\n",
    "                    left = left.parent\n",
    "                else:\n",
    "                    return left\n",
    "\n",
    "            if right:\n",
    "                if not right in d.keys():\n",
    "                    d[right] = 1\n",
    "                    right = right.parent\n",
    "                else:\n",
    "                    return right\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val):\n",
    "        self.val = val\n",
    "        self.left = None\n",
    "        self.right = None\n",
    "        self.parent = None\n",
    "\"\"\"\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, p: 'Node', q: 'Node') -> 'Node':\n",
    "        seen = set()\n",
    "        queue = collections.deque([p, q])\n",
    "        while queue:\n",
    "            curr = queue.popleft()\n",
    "            if curr in seen:\n",
    "                return curr\n",
    "            seen.add(curr)\n",
    "            if curr.parent:\n",
    "                queue.append(curr.parent)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution(object):\n",
    "    def lowestCommonAncestor(self, p, q):\n",
    "        \"\"\"\n",
    "        :type node: Node\n",
    "        :rtype: Node\n",
    "        \"\"\"\n",
    "        d = {}\n",
    "        left = p\n",
    "        right = q\n",
    "        while left or right:\n",
    "            if left:\n",
    "                if not left in d.keys():\n",
    "                    d[left] = 1\n",
    "                    left = left.parent\n",
    "                else:\n",
    "                    return left\n",
    "\n",
    "            if right:\n",
    "                if not right in d.keys():\n",
    "                    d[right] = 1\n",
    "                    right = right.parent\n",
    "                else:\n",
    "                    return right\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val):\n",
    "        self.val = val\n",
    "        self.left = None\n",
    "        self.right = None\n",
    "        self.parent = None\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, p: 'Node', q: 'Node') -> 'Node':\n",
    "        nodeSet = set()\n",
    "        while p:\n",
    "            nodeSet.add(p)\n",
    "            p = p.parent\n",
    "\n",
    "        while q:\n",
    "            if q in nodeSet:\n",
    "                return q\n",
    "\n",
    "            q = q.parent\n",
    "        return None\n",
    "        \n",
    "\n",
    "\n",
    "\n",
    "        \n",
    "\n",
    "\n",
    "\n",
    "            \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val):\n",
    "        self.val = val\n",
    "        self.left = None\n",
    "        self.right = None\n",
    "        self.parent = None\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, p: 'Node', q: 'Node') -> 'Node':\n",
    "        nodeSet = set()\n",
    "        while p:\n",
    "            nodeSet.add(p)\n",
    "            p = p.parent\n",
    "\n",
    "        while q:\n",
    "            if q in nodeSet:\n",
    "                return q\n",
    "\n",
    "            q = q.parent\n",
    "        return None\n",
    "        \n",
    "\n",
    "\n",
    "\n",
    "        \n",
    "\n",
    "\n",
    "\n",
    "            \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val):\n",
    "        self.val = val\n",
    "        self.left = None\n",
    "        self.right = None\n",
    "        self.parent = None\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, p: 'Node', q: 'Node') -> 'Node':\n",
    "        print('new case', p.val, q.val)\n",
    "        keep = set()\n",
    "        cur = p\n",
    "        while cur:\n",
    "            keep.add(cur.val)\n",
    "            cur = cur.parent\n",
    "\n",
    "        cur2 = q\n",
    "        while cur2:\n",
    "            if cur2.val in keep:\n",
    "                return cur2\n",
    "            else:\n",
    "                cur2 = cur2.parent\n",
    "\n",
    "        return "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val):\n",
    "        self.val = val\n",
    "        self.left = None\n",
    "        self.right = None\n",
    "        self.parent = None\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, p: 'Node', q: 'Node') -> 'Node':\n",
    "        s = set()\n",
    "        while p:\n",
    "            s.add(p)\n",
    "            p = p.parent\n",
    "            if q in s:\n",
    "                return q\n",
    "        while q:\n",
    "            if q in s:\n",
    "                return q \n",
    "            q = q.parent\n",
    "               \n",
    "\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val):\n",
    "        self.val = val\n",
    "        self.left = None\n",
    "        self.right = None\n",
    "        self.parent = None\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, p: 'Node', q: 'Node') -> 'Node':\n",
    "        nodeSet = set()\n",
    "        while p:\n",
    "            nodeSet.add(p)\n",
    "            p = p.parent\n",
    "\n",
    "        while q:\n",
    "            if q in nodeSet:\n",
    "                return q\n",
    "\n",
    "            q = q.parent\n",
    "        return None\n",
    "        \n",
    "\n",
    "\n",
    "\n",
    "        \n",
    "\n",
    "\n",
    "\n",
    "            \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val):\n",
    "        self.val = val\n",
    "        self.left = None\n",
    "        self.right = None\n",
    "        self.parent = None\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, p: 'Node', q: 'Node') -> 'Node':\n",
    "        s = set()\n",
    "\n",
    "        while p:\n",
    "            s.add(p)\n",
    "            p = p.parent\n",
    "        \n",
    "        while q:\n",
    "            if q in s:\n",
    "                return q\n",
    "            q = q.parent\n",
    "        \n",
    "        return None\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val):\n",
    "        self.val = val\n",
    "        self.left = None\n",
    "        self.right = None\n",
    "        self.parent = None\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, p: 'Node', q: 'Node') -> 'Node':\n",
    "\n",
    "        visited = set()\n",
    "        visited.add(p)\n",
    "        px = p \n",
    "        while px:\n",
    "            px = px.parent\n",
    "            visited.add(px)\n",
    "        \n",
    "        qx = q\n",
    "\n",
    "        while qx not in visited:\n",
    "            qx = qx.parent\n",
    "        return qx\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val):\n",
    "        self.val = val\n",
    "        self.left = None\n",
    "        self.right = None\n",
    "        self.parent = None\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, p: 'Node', q: 'Node') -> 'Node':\n",
    "        d = set()\n",
    "        cur = p\n",
    "        while cur:\n",
    "            d.add(cur)\n",
    "            cur = cur.parent\n",
    "        cur = q \n",
    "        while cur:\n",
    "            if cur in d:\n",
    "                return cur\n",
    "            cur = cur.parent\n",
    "        \n",
    "\n",
    "\n",
    "\n",
    "\n",
    "        # seen = set()\n",
    "        # queue = collections.deque([p, q])\n",
    "        # while queue:\n",
    "        #     cur = queue.popleft()\n",
    "        #     if cur in seen:\n",
    "        #         return cur\n",
    "        #     seen.add(cur)\n",
    "        #     if cur.parent:\n",
    "        #         queue.append(cur.parent)\n",
    "        \n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val):\n",
    "        self.val = val\n",
    "        self.left = None\n",
    "        self.right = None\n",
    "        self.parent = None\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    # Hashmap + iteration. Time O(n) Space O(n)\n",
    "    def lowestCommonAncestor(self, p: 'Node', q: 'Node') -> 'Node':\n",
    "        pParents = set()\n",
    "        cur = p\n",
    "        while cur:\n",
    "            pParents.add(cur)\n",
    "            cur = cur.parent\n",
    "        cur = q\n",
    "        while cur:\n",
    "            if cur in pParents:\n",
    "                return cur\n",
    "            cur = cur.parent\n",
    "        # This can be omitted as cur can go to root and pParents include root\n",
    "        # return cur"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val):\n",
    "        self.val = val\n",
    "        self.left = None\n",
    "        self.right = None\n",
    "        self.parent = None\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, p: 'Node', q: 'Node') -> 'Node':\n",
    "        def search_path(node):\n",
    "            path = set()\n",
    "            while(node):\n",
    "                path.add(node.val)\n",
    "                node = node.parent\n",
    "            return path\n",
    "        def search_path_(node, path):\n",
    "            while(node):\n",
    "                if node.val in path:\n",
    "                    return node\n",
    "                node = node.parent\n",
    "        return search_path_(p, search_path(q))\n",
    "    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val):\n",
    "        self.val = val\n",
    "        self.left = None\n",
    "        self.right = None\n",
    "        self.parent = None\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    # Hashmap + iteration. Time O(n) Space O(n)\n",
    "    def lowestCommonAncestor(self, p: 'Node', q: 'Node') -> 'Node':\n",
    "        pParents = set()\n",
    "        cur = p\n",
    "        while cur:\n",
    "            pParents.add(cur)\n",
    "            cur = cur.parent\n",
    "        cur = q\n",
    "        while cur:\n",
    "            if cur in pParents:\n",
    "                return cur\n",
    "            cur = cur.parent\n",
    "        # return cur"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val):\n",
    "        self.val = val\n",
    "        self.left = None\n",
    "        self.right = None\n",
    "        self.parent = None\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, p: 'Node', q: 'Node') -> 'Node':\n",
    "\n",
    "        visited = set()\n",
    "        visited.add(p)\n",
    "        px = p \n",
    "        while px:\n",
    "            px = px.parent\n",
    "            visited.add(px)\n",
    "        \n",
    "        qx = q\n",
    "\n",
    "        while qx:\n",
    "            if qx in visited:\n",
    "                return qx \n",
    "            qx = qx.parent\n",
    "        return None\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val):\n",
    "        self.val = val\n",
    "        self.left = None\n",
    "        self.right = None\n",
    "        self.parent = None\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, p: 'Node', q: 'Node') -> 'Node':\n",
    "        pPathSet = set()\n",
    "        while p:\n",
    "            pPathSet.add(p)\n",
    "            p = p.parent\n",
    "        while q:\n",
    "            if q in pPathSet:\n",
    "                return q\n",
    "            q = q.parent\n",
    "        return None"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', nodes1: 'List[TreeNode]') -> 'TreeNode':\n",
    "        depths, nodes = [], []\n",
    "        idx = {}\n",
    "        \n",
    "        def visit(root, depth):\n",
    "          if not root:\n",
    "            return\n",
    "          nonlocal depths, nodes, idx\n",
    "          visit(root.left, depth + 1)\n",
    "          idx[root] = len(nodes)\n",
    "          depths.append(depth)\n",
    "          nodes.append(root)\n",
    "          visit(root.right, depth + 1)\n",
    "        \n",
    "        visit(root, 0)\n",
    "        minIdx, maxIdx = len(nodes), -1\n",
    "        for node in nodes1:\n",
    "          minIdx = min(minIdx, idx[node])\n",
    "          maxIdx = max(maxIdx, idx[node])\n",
    "        \n",
    "        aIdx, aDepth = minIdx, depths[minIdx]\n",
    "        for i in range(minIdx, maxIdx+1):\n",
    "          if depths[i] < aDepth:\n",
    "            aDepth = depths[i]\n",
    "            aIdx = i\n",
    "        return nodes[aIdx]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', nodes: 'List[TreeNode]') -> 'TreeNode':\n",
    "        if root is None:\n",
    "            return None \n",
    "\n",
    "        if root in nodes:\n",
    "            return root\n",
    "\n",
    "        left = self.lowestCommonAncestor(root.left, nodes)\n",
    "        right = self.lowestCommonAncestor(root.right, nodes) \n",
    "\n",
    "        if left and right:\n",
    "            return root\n",
    "\n",
    "        return left if left else right"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', nodes: 'List[TreeNode]') -> 'TreeNode':\n",
    "        if root is None or root in nodes:\n",
    "            return root\n",
    "        left, right = self.lowestCommonAncestor(root.left, nodes), self.lowestCommonAncestor(root.right, nodes)\n",
    "        if left and right:\n",
    "            return root\n",
    "        return left if left else right\n",
    "# TC/SC: O(N)       \n",
    "\n",
    "    # def lowestCommonAncestor(self, root: TreeNode, p: TreeNode, q: TreeNode) -> TreeNode:\n",
    "    #     if root in (None, p, q):\n",
    "    #         return root\n",
    "    #     left = self.lowestCommonAncestor(root.left, p, q)\n",
    "    #     right = self.lowestCommonAncestor(root.right, p, q)\n",
    "    #     if left and right:\n",
    "    #         return root\n",
    "    #     return left if left else right"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', nodes: 'List[TreeNode]') -> 'TreeNode':\n",
    "        def lca(node):\n",
    "            if not node: \n",
    "                return None\n",
    "            if node in nodes: \n",
    "                return node\n",
    "            l, r = lca(node.left), lca(node.right)\n",
    "            if l and r: \n",
    "                return node\n",
    "            if l: \n",
    "                return l\n",
    "            if r: \n",
    "                return r\n",
    "        \n",
    "        return lca(root)\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', nodes: 'List[TreeNode]') -> 'TreeNode':\n",
    "        if not root:\n",
    "            return root\n",
    "        nodevals = [n.val for n in nodes]\n",
    "        return self.find(root, nodevals)\n",
    "        \n",
    "    def find(self, root, nodevals):\n",
    "        if not root:\n",
    "            return root\n",
    "        if root.val in nodevals:\n",
    "            return root\n",
    "        left = self.find(root.left, nodevals)\n",
    "        right = self.find(root.right, nodevals)\n",
    "        if left and right:\n",
    "            return root\n",
    "        if left:\n",
    "            return left\n",
    "        else:\n",
    "            return right\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', nodes: 'List[TreeNode]') -> 'TreeNode':\n",
    "        if not root or root in nodes:\n",
    "            return root\n",
    "        left = self.lowestCommonAncestor(root.left, nodes)\n",
    "        right = self.lowestCommonAncestor(root.right, nodes)\n",
    "        if left and right:\n",
    "            return root\n",
    "        return left if left else right       "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', nodes: 'List[TreeNode]'):\n",
    "        \n",
    "        def dfs(node):\n",
    "            if not node: return None\n",
    "            if node in nodes: return node\n",
    "            l, r = dfs(node.left), dfs(node.right)\n",
    "            if not l and not r: return None\n",
    "            if not l: return r\n",
    "            if not r: return l\n",
    "            return node\n",
    "        \n",
    "        return dfs(root)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', nodes: 'List[TreeNode]') -> 'TreeNode':\n",
    "        if root==None or (root in nodes):\n",
    "            return root\n",
    "        \n",
    "        l = self.lowestCommonAncestor(root.left, nodes)\n",
    "        r = self.lowestCommonAncestor(root.right, nodes)\n",
    "    \n",
    "        if r and l :\n",
    "            return root\n",
    "        \n",
    "        return l or r       "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', nodes: 'List[TreeNode]') -> 'TreeNode':\n",
    "        # dfs_LRN 后序遍历求LCA\n",
    "        if root==None or root in nodes:\n",
    "            return root\n",
    "        L = self.lowestCommonAncestor(root.left, nodes)\n",
    "        R = self.lowestCommonAncestor(root.right, nodes)\n",
    "        if L and R:\n",
    "            return root\n",
    "        elif L and not R:\n",
    "            return L\n",
    "        elif not L and R:\n",
    "            return R\n",
    "        else:\n",
    "            return None"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', nodes: 'List[TreeNode]') -> 'TreeNode':\n",
    "        if not root: return None\n",
    "        if root in nodes: return root\n",
    "        left, right = self.lowestCommonAncestor(root.left, nodes), self.lowestCommonAncestor(root.right, nodes)\n",
    "        if left and right: return root\n",
    "        elif not left and right: return right\n",
    "        elif left and not right: return left\n",
    "        else: return None"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', nodes: 'List[TreeNode]') -> 'TreeNode':\n",
    "        if not root:\n",
    "            return None\n",
    "        if root in nodes:\n",
    "            return root\n",
    "        left = self.lowestCommonAncestor(root.left, nodes)\n",
    "        right = self.lowestCommonAncestor(root.right, nodes)\n",
    "        if left and right:\n",
    "            return root\n",
    "        return left if left else right"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', nodes: 'List[TreeNode]') -> 'TreeNode':\n",
    "        if not root:\n",
    "            return root\n",
    "        if root in nodes:\n",
    "            return root\n",
    "        left = self.lowestCommonAncestor(root.left, nodes)\n",
    "        right=  self.lowestCommonAncestor(root.right, nodes)\n",
    "        if left and right:\n",
    "            return root\n",
    "        return left if left else right"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', nodes: 'List[TreeNode]') -> 'TreeNode':\n",
    "        def dfs(node):\n",
    "            if not node: return None\n",
    "            if node in nodes: return node\n",
    "            l, r = dfs(node.left), dfs(node.right)\n",
    "            if not l and not r: return None\n",
    "            if not l: return r\n",
    "            if not r: return l\n",
    "            return node\n",
    "        \n",
    "        return dfs(root)\n",
    "\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', nodes: 'List[TreeNode]') -> 'TreeNode':\n",
    "        if not root:return root\n",
    "        if root in nodes: return root\n",
    "        ls,rs = self.lowestCommonAncestor(root.left, nodes),self.lowestCommonAncestor(root.right, nodes)\n",
    "        if ls and rs: return root\n",
    "        return ls if ls else rs"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', nodes: 'List[TreeNode]') -> 'TreeNode':\n",
    "        \n",
    "        self.nodes = nodes\n",
    "\n",
    "        self.lenn = len(nodes)\n",
    "\n",
    "        self.sts = [False] * len(nodes)\n",
    "\n",
    "        return self.tr_(root)\n",
    "\n",
    "\n",
    "\n",
    "    def tr_(self, root):\n",
    "        \n",
    "        if root is None:\n",
    "            return None\n",
    "        \n",
    "\n",
    "        \n",
    "        for i in range(self.lenn):\n",
    "            if self.nodes[i] == root:\n",
    "                return root\n",
    "\n",
    "        left = self.tr_(root.left)\n",
    "        right = self.tr_(root.right)\n",
    "\n",
    "        if left and right:\n",
    "            return root\n",
    "        \n",
    "        return left if left else right\n",
    "        \n",
    "        \n",
    "        \n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', nodes: 'List[TreeNode]') -> 'TreeNode':\n",
    "        if not root:\n",
    "            return None\n",
    "        if root in nodes:\n",
    "            return root\n",
    "        \n",
    "        left = self.lowestCommonAncestor(root.left, nodes)\n",
    "        right = self.lowestCommonAncestor(root.right, nodes)\n",
    "        if left and right:\n",
    "            return root\n",
    "        \n",
    "        if left:\n",
    "            return left\n",
    "        else:\n",
    "            return right\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', nodes: 'List[TreeNode]') -> 'TreeNode':\n",
    "        def lca(node):\n",
    "            if not node: \n",
    "                return None\n",
    "            if node in nodes: \n",
    "                return node\n",
    "            l, r = lca(node.left), lca(node.right)\n",
    "            if l and r: \n",
    "                return node\n",
    "            if l: \n",
    "                return l\n",
    "            if r: \n",
    "                return r\n",
    "        \n",
    "        return lca(root)\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', nodes: 'List[TreeNode]') -> 'TreeNode':\n",
    "        def lca(node):\n",
    "            if not node: \n",
    "                return None\n",
    "            if node in nodes: \n",
    "                return node\n",
    "            l, r = lca(node.left), lca(node.right)\n",
    "            if l and r: \n",
    "                return node\n",
    "            if l: \n",
    "                return l\n",
    "            if r: \n",
    "                return r\n",
    "        \n",
    "        return lca(root)\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def find(self, root: TreeNode, nodes: List[TreeNode]) -> TreeNode:\n",
    "        if not root:\n",
    "            return None\n",
    "        if root.val in self.nodes:\n",
    "            return root\n",
    "        \n",
    "        left = self.find(root.left, nodes)\n",
    "        right = self.find(root.right, nodes)\n",
    "\n",
    "        if left and right:\n",
    "            return root\n",
    "        \n",
    "        return left if left else right\n",
    "\n",
    "\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', nodes: 'List[TreeNode]') -> 'TreeNode':\n",
    "        self.nodes = []\n",
    "        for n in nodes:\n",
    "            self.nodes.append(n.val)\n",
    "        \n",
    "        return self.find(root, nodes)\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', nodes: 'List[TreeNode]') -> 'TreeNode':\n",
    "       \n",
    "        def dfs(node):\n",
    "            if not node or node in nodes: return node\n",
    "            left = dfs(node.left)\n",
    "            right = dfs(node.right)\n",
    "            if not left and not right: return # 1.\n",
    "            if not left: return right # 3.\n",
    "            if not right: return left # 4.\n",
    "            return node # 2. if left and right:\n",
    "        \n",
    "        return dfs(root)\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', nodes: 'List[TreeNode]') -> 'TreeNode':\n",
    "        def dfs(node):\n",
    "            if not node: return None\n",
    "            if node in nodes: return node\n",
    "            l, r = dfs(node.left), dfs(node.right)\n",
    "            if not l and not r: return None\n",
    "            if not l: return r\n",
    "            if not r: return l\n",
    "            return node\n",
    "        \n",
    "        return dfs(root)\n",
    "        # https://www.youtube.com/watch?v=6-q4KywBGAY\n",
    "\n",
    "\n",
    "            \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', nodes: 'List[TreeNode]') -> 'TreeNode':\n",
    "        if not root: return None\n",
    "        # 前序遍历\n",
    "        # 中\n",
    "        if root.val in [n.val for n in nodes]:\n",
    "            return root\n",
    "        \n",
    "        # 左右\n",
    "        # 在左子树中寻找是否存在目标节点\n",
    "        left = self.lowestCommonAncestor(root.left, nodes)\n",
    "        # 在右子树中寻找是否存在目标节点\n",
    "        right = self.lowestCommonAncestor(root.right, nodes)\n",
    "\n",
    "        # 若在左右子树中都能够找到目标节点，则返回当前的root\n",
    "        if left and right: return root\n",
    "        # 若在左侧找不到，则说明最近公共祖先在右子树中\n",
    "        # 因为确保了待查元素一定在当前树种\n",
    "        if not left: return right\n",
    "        return left"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', nodes: 'List[TreeNode]') -> 'TreeNode':\n",
    "        def dfs(node):\n",
    "            if not node: return None\n",
    "            if node in nodes: return node\n",
    "            l, r = dfs(node.left), dfs(node.right)\n",
    "            if not l and not r: return None\n",
    "            elif not l: return r\n",
    "            elif not r: return l\n",
    "            return node\n",
    "        return dfs(root)\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', nodes: 'List[TreeNode]') -> 'TreeNode':\n",
    "        def lca(node):\n",
    "            if not node: \n",
    "                return None\n",
    "            if node in nodes: \n",
    "                return node\n",
    "            l, r = lca(node.left), lca(node.right)\n",
    "            if l and r: \n",
    "                return node\n",
    "            if l: \n",
    "                return l\n",
    "            if r: \n",
    "                return r\n",
    "        \n",
    "        return lca(root)\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', nodes: 'List[TreeNode]') -> 'TreeNode':\n",
    "        def f(x, y):\n",
    "            if (not x) or x in y:\n",
    "                return x\n",
    "            a = f(x.left, y)\n",
    "            b = f(x.right, y)\n",
    "            if a and b:\n",
    "                return x\n",
    "            return a if a else b\n",
    "\n",
    "\n",
    "        return f(root, nodes)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def __init__(self):\n",
    "        self.values = {}\n",
    "\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', nodes: 'List[TreeNode]') -> 'TreeNode':\n",
    "        for i in nodes:\n",
    "            self.values[i.val] = 1 # 把要查找的节点值存起来\n",
    "        return self.traverse(root)\n",
    "    \n",
    "    def traverse(self,root):\n",
    "        if not root:\n",
    "            return None\n",
    "        if root.val in self.values.keys():\n",
    "            return root\n",
    "\n",
    "        left = self.traverse(root.left)\n",
    "        right = self.traverse(root.right)\n",
    "\n",
    "        if left!=None and right!=None:\n",
    "            return root\n",
    "        \n",
    "        if left==None:\n",
    "            return right\n",
    "        else:\n",
    "            return left\n",
    "        \n",
    "        if left==None and right==None:\n",
    "            return None\n",
    "\n",
    "        \n",
    "\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', nodes: 'List[TreeNode]') -> 'TreeNode':\n",
    "        \n",
    "        def dfs(node):\n",
    "            if not node: return None\n",
    "            if node in nodes: return node\n",
    "            l, r = dfs(node.left), dfs(node.right)\n",
    "            if not l and not r: return None\n",
    "            if not l: return r\n",
    "            if not r: return l\n",
    "            return node\n",
    "        \n",
    "        return dfs(root)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', nodes: 'List[TreeNode]') -> 'TreeNode':\n",
    "        def dfs(node):\n",
    "            if not node: \n",
    "                return None\n",
    "            if node in nodes: \n",
    "                return node\n",
    "            l, r = dfs(node.left), dfs(node.right)\n",
    "            if l and r: \n",
    "                return node\n",
    "            if l: \n",
    "                return l\n",
    "            if r: \n",
    "                return r\n",
    "\n",
    "        return dfs(root)\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', nodes: 'List[TreeNode]') -> 'TreeNode':\n",
    "        if root is None:\n",
    "            return None\n",
    "        if root in nodes:\n",
    "            return root\n",
    "        \n",
    "        left = self.lowestCommonAncestor(root.left, nodes)\n",
    "        right = self.lowestCommonAncestor(root.right, nodes)\n",
    "        if left and right:\n",
    "            return root\n",
    "        \n",
    "        return left or right"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', nodes: 'List[TreeNode]') -> 'TreeNode':\n",
    "        @cache\n",
    "        def dfs(node):\n",
    "            if not node or node in nodes:\n",
    "                return node\n",
    "            l, r = dfs(node.left), dfs(node.right)\n",
    "            if l and r:\n",
    "                return node \n",
    "            return l if l else r\n",
    "        return dfs(root)\n",
    "    \n",
    "\n",
    "        \n",
    "        # def helper(l, r):\n",
    "        #     if l == r:\n",
    "        #         return nodes[l]\n",
    "        #     elif l + 1 == r:\n",
    "        #         return dfs(root, nodes[l], nodes[r])\n",
    "        #     m = l + r >> 1\n",
    "        #     ln = helper(l, m)\n",
    "        #     rn = helper(m + 1, r)\n",
    "        #     return dfs(root, ln, rn)\n",
    "        # return helper(0, len(nodes) - 1)\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', nodes: 'List[TreeNode]') -> 'TreeNode':\n",
    "        if not root:\n",
    "            return None\n",
    "        if root in nodes:\n",
    "            return root\n",
    "        left = self.lowestCommonAncestor(root.left, nodes)\n",
    "        right = self.lowestCommonAncestor(root.right, nodes)\n",
    "        if left != None and right != None:\n",
    "            return root\n",
    "        if left != None and right == None:\n",
    "            return left\n",
    "        elif right != None and left == None:\n",
    "            return right\n",
    "        else:\n",
    "            return None\n",
    "        \n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', nodes: 'List[TreeNode]') -> 'TreeNode':\n",
    "        if not root:\n",
    "            return\n",
    "        for node in nodes:\n",
    "            if root.val == node.val:\n",
    "                return root\n",
    "        l = self.lowestCommonAncestor(root.left, nodes)\n",
    "        r = self.lowestCommonAncestor(root.right, nodes)\n",
    "        if l and r:\n",
    "            return root\n",
    "        elif l and not r:\n",
    "            return l\n",
    "        elif r and not l:\n",
    "            return r\n",
    "        else:\n",
    "            return "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', nodes: 'List[TreeNode]') -> 'TreeNode':\n",
    "        st = set(x.val for x in nodes)\n",
    "        def dfs(node):\n",
    "            if not node or node.val in st:\n",
    "                return node\n",
    "            l, r = dfs(node.left), dfs(node.right)\n",
    "            if l and r:\n",
    "                return node \n",
    "            return l or r\n",
    "        return dfs(root)\n",
    "    \n",
    "\n",
    "        \n",
    "        # def helper(l, r):\n",
    "        #     if l == r:\n",
    "        #         return nodes[l]\n",
    "        #     elif l + 1 == r:\n",
    "        #         return dfs(root, nodes[l], nodes[r])\n",
    "        #     m = l + r >> 1\n",
    "        #     ln = helper(l, m)\n",
    "        #     rn = helper(m + 1, r)\n",
    "        #     return dfs(root, ln, rn)\n",
    "        # return helper(0, len(nodes) - 1)\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', nodes: 'List[TreeNode]') -> 'TreeNode':\n",
    "        vals = {node.val for node in nodes}\n",
    "\n",
    "        def dfs(root):\n",
    "            if root is None:\n",
    "                return root\n",
    "            if root.val in vals:\n",
    "                return root\n",
    "            left = dfs(root.left)\n",
    "            right = dfs(root.right)\n",
    "            if left and right:\n",
    "                return root\n",
    "            return left or right\n",
    "\n",
    "        return dfs(root)\n",
    "    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', nodes: 'List[TreeNode]') -> 'TreeNode':\n",
    "        st = {x.val for x in nodes}\n",
    "        def dfs(node):\n",
    "            if not node or node.val in st:\n",
    "                return node\n",
    "            l, r = dfs(node.left), dfs(node.right)\n",
    "            if l and r:\n",
    "                return node \n",
    "            return l or r\n",
    "        return dfs(root)\n",
    "    \n",
    "\n",
    "        \n",
    "        # def helper(l, r):\n",
    "        #     if l == r:\n",
    "        #         return nodes[l]\n",
    "        #     elif l + 1 == r:\n",
    "        #         return dfs(root, nodes[l], nodes[r])\n",
    "        #     m = l + r >> 1\n",
    "        #     ln = helper(l, m)\n",
    "        #     rn = helper(m + 1, r)\n",
    "        #     return dfs(root, ln, rn)\n",
    "        # return helper(0, len(nodes) - 1)\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', nodes: 'List[TreeNode]') -> 'TreeNode':\n",
    "        needs = set(nodes)\n",
    "        def dfs(node):\n",
    "            if not node:\n",
    "                return\n",
    "            if node in needs:\n",
    "                return node\n",
    "            left = dfs(node.left)\n",
    "            right = dfs(node.right)\n",
    "            if left and right:\n",
    "                return node\n",
    "            if left:\n",
    "                return left \n",
    "            if right:\n",
    "                return right\n",
    "            return\n",
    "        return dfs(root)\n",
    "\n",
    "\n",
    "\n",
    "        # needs = set(nodes)\n",
    "        \n",
    "        # def dfs(node):\n",
    "        #     if not node:\n",
    "        #         return (None, 0)\n",
    "        #     left, left_cnt = dfs(node.left)\n",
    "        #     right, right_cnt = dfs(node.right)\n",
    "        #     if left_cnt == len(needs):\n",
    "        #         return (left, left_cnt)\n",
    "        #     if right_cnt == len(needs):\n",
    "        #         return (right, right_cnt)\n",
    "        #     if node in needs:\n",
    "        #         return (node, 1 + left_cnt + right_cnt)\n",
    "        #     if left and right:\n",
    "        #         return (node, left_cnt+right_cnt)\n",
    "        #     if left:\n",
    "        #         return (left, left_cnt)\n",
    "        #     if right:\n",
    "        #         return (right, right_cnt)\n",
    "        #     return (None, 0)\n",
    "    \n",
    "        # return dfs(root)[0]\n",
    "        \n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', nodes: 'List[TreeNode]') -> 'TreeNode':\n",
    "        needs = set(nodes)\n",
    "        def dfs(node):\n",
    "            if not node:\n",
    "                return \n",
    "            if node in needs:\n",
    "                return node\n",
    "            left = dfs(node.left)\n",
    "            right = dfs(node.right)\n",
    "            if left and right:\n",
    "                return node\n",
    "            if left:\n",
    "                return left\n",
    "            if right:\n",
    "                return right\n",
    "            return \n",
    "        return dfs(root)\n",
    "        \n",
    "\n",
    "\n",
    "\n",
    "\n",
    "        # needs = set(nodes)\n",
    "        # def dfs(node):\n",
    "        #     if not node:\n",
    "        #         return\n",
    "        #     if node in needs:\n",
    "        #         return node\n",
    "        #     left = dfs(node.left)\n",
    "        #     right = dfs(node.right)\n",
    "        #     if left and right:\n",
    "        #         return node\n",
    "        #     if left:\n",
    "        #         return left \n",
    "        #     if right:\n",
    "        #         return right\n",
    "        #     return\n",
    "        # return dfs(root)\n",
    "\n",
    "\n",
    "\n",
    "        # needs = set(nodes)\n",
    "        \n",
    "        # def dfs(node):\n",
    "        #     if not node:\n",
    "        #         return (None, 0)\n",
    "        #     left, left_cnt = dfs(node.left)\n",
    "        #     right, right_cnt = dfs(node.right)\n",
    "        #     if node in needs:\n",
    "        #         return (node, 1 + left_cnt + right_cnt)\n",
    "        #     if left and right:\n",
    "        #         return (node, left_cnt+right_cnt)\n",
    "        #     if left:\n",
    "        #         return (left, left_cnt)\n",
    "        #     if right:\n",
    "        #         return (right, right_cnt)\n",
    "        #     return (None, 0)\n",
    "    \n",
    "        # return dfs(root)[0]\n",
    "        \n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: TreeNode, nodes: List[TreeNode]) -> TreeNode:\n",
    "        # 转化到集合中\n",
    "        node_vals = set(node.val for node in nodes)\n",
    "        return self.LCA(root, node_vals)\n",
    "\n",
    "    def LCA(self, root: TreeNode, node_vals: Set[int]) -> TreeNode:\n",
    "        # base case\n",
    "        if root is None:\n",
    "            return None\n",
    "        if root.val in node_vals:\n",
    "            return root\n",
    "\n",
    "        left = self.LCA(root.left, node_vals)\n",
    "        right = self.LCA(root.right, node_vals)\n",
    "        # 情况 1\n",
    "        if left is not None and right is not None:\n",
    "            return root\n",
    "        # 情况 2\n",
    "        if left is None and right is None:\n",
    "            return None\n",
    "        # 情况 3\n",
    "        return right if left is None else left"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', nodes: 'List[TreeNode]') -> 'TreeNode':\n",
    "        val_set = set([node.val for node in nodes])\n",
    "        return self.find(root, val_set)\n",
    "    def find(self, root, val_set):\n",
    "        if root == None:\n",
    "            return None\n",
    "        if root.val in val_set:\n",
    "            return root\n",
    "        left = self.find(root.left, val_set)\n",
    "        right = self.find(root.right, val_set)\n",
    "        if left and right:\n",
    "            return root\n",
    "        return left if left else right\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def _lowestCommonAncestor(self, root, nodes):\n",
    "        if not root:\n",
    "            return None\n",
    "        if root in nodes:\n",
    "            return root\n",
    "        leftRes = self._lowestCommonAncestor(root.left, nodes)\n",
    "        rightRes = self._lowestCommonAncestor(root.right, nodes)\n",
    "        if leftRes and rightRes:\n",
    "            return root\n",
    "        if leftRes:\n",
    "            return leftRes\n",
    "        if rightRes:\n",
    "            return rightRes\n",
    "        return None\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', nodes: 'List[TreeNode]') -> 'TreeNode':\n",
    "        nodes = set(nodes)\n",
    "\n",
    "        return self._lowestCommonAncestor(root, nodes)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', nodes: 'List[TreeNode]') -> 'TreeNode':\n",
    "        # O(n)\n",
    "        visited = set()\n",
    "        for t in nodes:\n",
    "            visited.add(t.val)\n",
    "        \n",
    "\n",
    "        def dfs(root, visited):\n",
    "            if not root:\n",
    "                return None\n",
    "            if root.val in visited:\n",
    "                return root\n",
    "            left = dfs(root.left, visited)\n",
    "            right = dfs(root.right, visited)\n",
    "            if left and right:\n",
    "                return root\n",
    "            if left:\n",
    "                return left\n",
    "            if right:\n",
    "                return right\n",
    "            return None\n",
    "        \n",
    "        return dfs(root, visited)\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', nodes: 'List[TreeNode]') -> 'TreeNode':\n",
    "        st = set(nodes)\n",
    "        def dfs(node):\n",
    "            if not node or node in st:\n",
    "                return node\n",
    "            l, r = dfs(node.left), dfs(node.right)\n",
    "            if l and r:\n",
    "                return node \n",
    "            return l or r\n",
    "        return dfs(root)\n",
    "    \n",
    "\n",
    "        \n",
    "        # def helper(l, r):\n",
    "        #     if l == r:\n",
    "        #         return nodes[l]\n",
    "        #     elif l + 1 == r:\n",
    "        #         return dfs(root, nodes[l], nodes[r])\n",
    "        #     m = l + r >> 1\n",
    "        #     ln = helper(l, m)\n",
    "        #     rn = helper(m + 1, r)\n",
    "        #     return dfs(root, ln, rn)\n",
    "        # return helper(0, len(nodes) - 1)\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', nodes: 'List[TreeNode]') -> 'TreeNode':\n",
    "\n",
    "        s = set([node.val for node in nodes])\n",
    "\n",
    "        def tree(root, s):\n",
    "            if not root:\n",
    "                return\n",
    "            if root.val in s:\n",
    "                return root\n",
    "            left = tree(root.left, s)\n",
    "            right = tree(root.right, s)\n",
    "            if left and right:\n",
    "                return root\n",
    "            else:\n",
    "                return left or right\n",
    "        return tree(root, s)\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "class TreeNode:\n",
    "    def __init__(self, x):\n",
    "        self.val = x\n",
    "        self.left = None\n",
    "        self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', nodes: 'List[TreeNode]') -> 'TreeNode':\n",
    "        \n",
    "        # 转化nodes为集合，以便更快速地检查节点是否在nodes中\n",
    "        nodes_set = set(nodes)\n",
    "        \n",
    "        def helper(node):\n",
    "            # 如果节点为空或在nodes中，返回节点\n",
    "            if not node or node in nodes_set:\n",
    "                return node\n",
    "            \n",
    "            # 查找左右子树的公共祖先\n",
    "            left_lca = helper(node.left)\n",
    "            right_lca = helper(node.right)\n",
    "            \n",
    "            # 如果左右子树的公共祖先都存在，当前节点是公共祖先\n",
    "            if left_lca and right_lca:\n",
    "                return node\n",
    "            # 否则，返回存在的那个\n",
    "            return left_lca if left_lca else right_lca\n",
    "        \n",
    "        return helper(root)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', nodes: 'List[TreeNode]') -> 'TreeNode':\n",
    "        s = set(nodes)\n",
    "\n",
    "        def dfs(root):\n",
    "            if not root or root in s:\n",
    "                return root\n",
    "            left,right = dfs(root.left),dfs(root.right)\n",
    "            if left and right:\n",
    "                return root\n",
    "            return left if left else right\n",
    "        \n",
    "        return dfs(root)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', nodes: 'List[TreeNode]') -> 'TreeNode':\n",
    "        def dfs(root, nodes, n):\n",
    "            stack = [root]\n",
    "            path = set()\n",
    "            visited = set()\n",
    "            meet_num = 0\n",
    "            while(stack):\n",
    "                cur = stack[-1]\n",
    "                if cur is None:\n",
    "                    stack.pop()\n",
    "                    continue\n",
    "                if cur.val in visited:\n",
    "                    if meet_num == n and cur.val in path:\n",
    "                        return cur\n",
    "                    stack.pop()\n",
    "                    if meet_num == 0:\n",
    "                        path.discard(cur.val)\n",
    "                    continue\n",
    "                if meet_num == 0:\n",
    "                    path.add(cur.val)\n",
    "                visited.add(cur.val)\n",
    "                if cur in nodes:\n",
    "                    meet_num += 1\n",
    "                stack.append(cur.left)\n",
    "                stack.append(cur.right)\n",
    "            return None\n",
    "        return dfs(root, nodes, len(nodes))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', nodes: 'List[TreeNode]') -> 'TreeNode':\n",
    "        nodeVal = set()\n",
    "        for i in nodes:\n",
    "            nodeVal.add(i.val)\n",
    "        \n",
    "        return self.function(root, nodeVal)\n",
    "    \n",
    "    def function(self, root, nodeVal):\n",
    "        if not root:\n",
    "            return\n",
    "        \n",
    "        if root.val in nodeVal:\n",
    "            return root\n",
    "        \n",
    "        left = self.function(root.left, nodeVal)\n",
    "        right = self.function(root.right, nodeVal)\n",
    "\n",
    "        if left and right:\n",
    "            return root\n",
    "        \n",
    "        return left if left else right"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', nodes: 'List[TreeNode]') -> 'TreeNode':\n",
    "        def dfs(root, nodes, n):\n",
    "            stack = [root]\n",
    "            path = set()\n",
    "            visited = set()\n",
    "            meet_num = 0\n",
    "            while(stack):\n",
    "                cur = stack[-1]\n",
    "                if cur is None:\n",
    "                    stack.pop()\n",
    "                    continue\n",
    "                if cur.val in visited:\n",
    "                    if meet_num == n and cur.val in path:\n",
    "                        return cur\n",
    "                    stack.pop()\n",
    "                    path.discard(cur.val)\n",
    "                    continue\n",
    "                if meet_num == 0:\n",
    "                    path.add(cur.val)\n",
    "                visited.add(cur.val)\n",
    "                if cur in nodes:\n",
    "                    meet_num += 1\n",
    "                stack.append(cur.left)\n",
    "                stack.append(cur.right)\n",
    "            return None\n",
    "        return dfs(root, nodes, len(nodes))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', nodes: 'List[TreeNode]') -> 'TreeNode':\n",
    "        def dfs(root, nodes, n):\n",
    "            stack = [root]\n",
    "            visited = set()\n",
    "            ress = []\n",
    "            while(stack):\n",
    "                cur = stack[-1]\n",
    "                if cur is None:\n",
    "                    ress.append(0)\n",
    "                    stack.pop()\n",
    "                    continue\n",
    "                if cur.val in visited:\n",
    "                    tmp = (cur in nodes) + ress.pop() + ress.pop()\n",
    "                    if tmp == n:\n",
    "                        return cur\n",
    "                    ress.append(tmp)\n",
    "                    stack.pop()\n",
    "                    continue\n",
    "                visited.add(cur.val)\n",
    "                stack.append(cur.left)\n",
    "                stack.append(cur.right)\n",
    "        return dfs(root, nodes, len(nodes))\n",
    "        # def dfs(root, nodes, n):\n",
    "        #     stack = [root]\n",
    "        #     path = set()\n",
    "        #     visited = set()\n",
    "        #     meet_num = 0\n",
    "        #     while(stack):\n",
    "        #         cur = stack[-1]\n",
    "        #         if cur is None:\n",
    "        #             stack.pop()\n",
    "        #             continue\n",
    "        #         if cur.val in visited:\n",
    "        #             if meet_num == n and cur.val in path:\n",
    "        #                 return cur\n",
    "        #             stack.pop()\n",
    "        #             if meet_num == 0:\n",
    "        #                 path.discard(cur.val)\n",
    "        #             continue\n",
    "        #         if meet_num == 0:\n",
    "        #             path.add(cur.val)\n",
    "        #         visited.add(cur.val)\n",
    "        #         if cur in nodes:\n",
    "        #             meet_num += 1\n",
    "        #         stack.append(cur.left)\n",
    "        #         stack.append(cur.right)\n",
    "        #     return None\n",
    "        # return dfs(root, nodes, len(nodes))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', nodes: 'List[TreeNode]') -> 'TreeNode':\n",
    "        def dfs(node):\n",
    "            if node == None:\n",
    "                return 0\n",
    "            res = 0\n",
    "            if node in nodes:\n",
    "                res += 1\n",
    "            res += dfs(node.left) + dfs(node.right)\n",
    "            if res == len(nodes):\n",
    "                return\n",
    "        def dfs(root, nodes, n):\n",
    "            stack = [root]\n",
    "            visited = set()\n",
    "            ress = []\n",
    "            while(stack):\n",
    "                cur = stack[-1]\n",
    "                if cur is None:\n",
    "                    ress.append(0)\n",
    "                    stack.pop()\n",
    "                    continue\n",
    "                if cur.val in visited:\n",
    "                    tmp = (cur in nodes) + ress.pop() + ress.pop()\n",
    "                    if tmp == n:\n",
    "                        return cur\n",
    "                    ress.append(tmp)\n",
    "                    stack.pop()\n",
    "                    continue\n",
    "                visited.add(cur.val)\n",
    "                stack.append(cur.left)\n",
    "                stack.append(cur.right)\n",
    "        return dfs(root, nodes, len(nodes))\n",
    "        # def dfs(root, nodes, n):\n",
    "        #     stack = [root]\n",
    "        #     path = set()\n",
    "        #     visited = set()\n",
    "        #     meet_num = 0\n",
    "        #     while(stack):\n",
    "        #         cur = stack[-1]\n",
    "        #         if cur is None:\n",
    "        #             stack.pop()\n",
    "        #             continue\n",
    "        #         if cur.val in visited:\n",
    "        #             if meet_num == n and cur.val in path:\n",
    "        #                 return cur\n",
    "        #             stack.pop()\n",
    "        #             if meet_num == 0:\n",
    "        #                 path.discard(cur.val)\n",
    "        #             continue\n",
    "        #         if meet_num == 0:\n",
    "        #             path.add(cur.val)\n",
    "        #         visited.add(cur.val)\n",
    "        #         if cur in nodes:\n",
    "        #             meet_num += 1\n",
    "        #         stack.append(cur.left)\n",
    "        #         stack.append(cur.right)\n",
    "        #     return None\n",
    "        # return dfs(root, nodes, len(nodes))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', nodes: 'List[TreeNode]') -> 'TreeNode':\n",
    "        def dfs(root, nodes, n):\n",
    "            stack = [root]\n",
    "            visited = set()\n",
    "            ress = []\n",
    "            while(stack):\n",
    "                cur = stack[-1]\n",
    "                if cur is None:\n",
    "                    ress.append(0)\n",
    "                    stack.pop()\n",
    "                    continue\n",
    "                if cur.val in visited:\n",
    "                    tmp = (cur in nodes) + ress.pop() + ress.pop()\n",
    "                    if tmp == n:\n",
    "                        return cur\n",
    "                    ress.append(tmp)\n",
    "                    stack.pop()\n",
    "                    continue\n",
    "                visited.add(cur.val)\n",
    "                stack.append(cur.left)\n",
    "                stack.append(cur.right)\n",
    "        return dfs(root, set(nodes), len(nodes))\n",
    "        # def dfs(root, nodes, n):\n",
    "        #     stack = [root]\n",
    "        #     path = set()\n",
    "        #     visited = set()\n",
    "        #     meet_num = 0\n",
    "        #     while(stack):\n",
    "        #         cur = stack[-1]\n",
    "        #         if cur is None:\n",
    "        #             stack.pop()\n",
    "        #             continue\n",
    "        #         if cur.val in visited:\n",
    "        #             if meet_num == n and cur.val in path:\n",
    "        #                 return cur\n",
    "        #             stack.pop()\n",
    "        #             if meet_num == 0:\n",
    "        #                 path.discard(cur.val)\n",
    "        #             continue\n",
    "        #         if meet_num == 0:\n",
    "        #             path.add(cur.val)\n",
    "        #         visited.add(cur.val)\n",
    "        #         if cur in nodes:\n",
    "        #             meet_num += 1\n",
    "        #         stack.append(cur.left)\n",
    "        #         stack.append(cur.right)\n",
    "        #     return None\n",
    "        # return dfs(root, nodes, len(nodes))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', nodes: 'List[TreeNode]') -> 'TreeNode':\n",
    "        # def dfs(root, nodes, n):\n",
    "        #     stack = [root]\n",
    "        #     visited = set()\n",
    "        #     ress = []\n",
    "        #     while(stack):\n",
    "        #         cur = stack[-1]\n",
    "        #         if cur is None:\n",
    "        #             ress.append(0)\n",
    "        #             stack.pop()\n",
    "        #             continue\n",
    "        #         if cur.val in visited:\n",
    "        #             tmp = (cur in nodes) + ress.pop() + ress.pop()\n",
    "        #             if tmp == n:\n",
    "        #                 return cur\n",
    "        #             ress.append(tmp)\n",
    "        #             stack.pop()\n",
    "        #             continue\n",
    "        #         visited.add(cur.val)\n",
    "        #         stack.append(cur.left)\n",
    "        #         stack.append(cur.right)\n",
    "        # return dfs(root, set(nodes), len(nodes))\n",
    "        def dfs(root, nodes, n):\n",
    "            stack = [root]\n",
    "            path = set()\n",
    "            visited = set()\n",
    "            meet_num = 0\n",
    "            while(stack):\n",
    "                cur = stack[-1]\n",
    "                if cur is None:\n",
    "                    stack.pop()\n",
    "                    continue\n",
    "                if cur.val in visited:\n",
    "                    if meet_num == n and cur.val in path:\n",
    "                        return cur\n",
    "                    stack.pop()\n",
    "                    if meet_num == 0:\n",
    "                        path.discard(cur.val)\n",
    "                    continue\n",
    "                if meet_num == 0:\n",
    "                    path.add(cur.val)\n",
    "                visited.add(cur.val)\n",
    "                if cur in nodes:\n",
    "                    meet_num += 1\n",
    "                stack.append(cur.left)\n",
    "                stack.append(cur.right)\n",
    "            return None\n",
    "        return dfs(root, set(nodes), len(nodes))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', nodes: 'List[TreeNode]') -> 'TreeNode':\n",
    "        def lca(root,node1,node2):\n",
    "            if not root or root==node1 or root==node2:\n",
    "                return root\n",
    "            L=lca(root.left,node1,node2)\n",
    "            R=lca(root.right,node1,node2)\n",
    "            if L and R:\n",
    "                return root\n",
    "            else :\n",
    "                return L or R\n",
    "        cur=nodes[0]\n",
    "        for node in nodes:\n",
    "            cur=lca(root,cur,node)\n",
    "        return cur\n",
    "\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution(object):\n",
    "    def lowestCommonAncestor(self, root, nodes):\n",
    "        \"\"\"\n",
    "        :type root: TreeNode\n",
    "        :type nodes: List[TreeNode]\n",
    "        \"\"\"\n",
    "        if len(nodes) == 1:\n",
    "            return nodes[0]\n",
    "        elif len(nodes) == 0:\n",
    "            return None\n",
    "        self.count = 0\n",
    "        self.ans = None\n",
    "        \n",
    "        def postOrder(root, nodes):\n",
    "            if not root:\n",
    "                return 0\n",
    "            curCount = 0\n",
    "            left = postOrder(root.left, nodes)\n",
    "            if left == len(nodes)+1:\n",
    "                return left\n",
    "            curCount += left\n",
    "            right = postOrder(root.right, nodes)\n",
    "            if right == len(nodes)+1:\n",
    "                return right    \n",
    "            curCount += right\n",
    "            if root in nodes:\n",
    "                curCount += 1\n",
    "            if curCount == len(nodes):\n",
    "                self.ans = root\n",
    "                return curCount + 1\n",
    "            else:\n",
    "                return curCount\n",
    "\n",
    "        postOrder(root, nodes)\n",
    "        return self.ans\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution(object):\n",
    "    def lowestCommonAncestor(self, root, nodes):\n",
    "        \"\"\"\n",
    "        :type root: TreeNode\n",
    "        :type nodes: List[TreeNode]\n",
    "        \"\"\"\n",
    "        if len(nodes) == 1:\n",
    "            return nodes[0]\n",
    "        elif len(nodes) == 0:\n",
    "            return None\n",
    "        self.count = 0\n",
    "        self.ans = None\n",
    "        \n",
    "        def postOrder(root, nodes):\n",
    "            if not root:\n",
    "                return 0\n",
    "            curCount = 0\n",
    "            left = postOrder(root.left, nodes)\n",
    "            if left == len(nodes)+1:\n",
    "                return left\n",
    "            curCount += left\n",
    "            right = postOrder(root.right, nodes)\n",
    "            if right == len(nodes)+1:\n",
    "                return right    \n",
    "            curCount += right\n",
    "            if root in nodes:\n",
    "                curCount += 1\n",
    "            if curCount == len(nodes):\n",
    "                self.ans = root\n",
    "                return curCount + 1\n",
    "            else:\n",
    "                return curCount\n",
    "\n",
    "        postOrder(root, nodes)\n",
    "        return self.ans\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution(object):\n",
    "    def lowestCommonAncestor(self, root, nodes):\n",
    "        \"\"\"\n",
    "        :type root: TreeNode\n",
    "        :type nodes: List[TreeNode]\n",
    "        \"\"\"\n",
    "        if len(nodes) == 1:\n",
    "            return nodes[0]\n",
    "        elif len(nodes) == 0:\n",
    "            return None\n",
    "        self.count = 0\n",
    "        self.ans = None\n",
    "        \n",
    "        def postOrder(root, nodes):\n",
    "            if not root:\n",
    "                return 0\n",
    "            curCount = 0\n",
    "            left = postOrder(root.left, nodes)\n",
    "            if left == len(nodes)+1:\n",
    "                return left\n",
    "            curCount += left\n",
    "            right = postOrder(root.right, nodes)\n",
    "            if right == len(nodes)+1:\n",
    "                return right    \n",
    "            curCount += right\n",
    "            if root in nodes:\n",
    "                curCount += 1\n",
    "            if curCount == len(nodes):\n",
    "                self.ans = root\n",
    "                return curCount + 1\n",
    "            else:\n",
    "                return curCount\n",
    "\n",
    "        postOrder(root, nodes)\n",
    "        return self.ans\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', nodes: 'List[TreeNode]') -> 'TreeNode':\n",
    "        ret = []\n",
    "        target = len(nodes)\n",
    "        def countNodes(root) -> int:\n",
    "            nonlocal ret, target, nodes\n",
    "            if not root:\n",
    "                return 0\n",
    "            count = 0\n",
    "            for n in nodes:\n",
    "                if root == n:\n",
    "                    count += 1\n",
    "                    nodes.remove(n)\n",
    "                    break\n",
    "            count += countNodes(root.left)\n",
    "            if ret:\n",
    "                return target\n",
    "            if count < target:\n",
    "                count += countNodes(root.right)\n",
    "            if count == target:\n",
    "                ret.append(root)\n",
    "            return count\n",
    "        countNodes(root)\n",
    "        if ret:\n",
    "            return ret[0]\n",
    "        return None"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', nodes: 'List[TreeNode]') -> 'TreeNode':\n",
    "        vals = {node.val for node in nodes}\n",
    "\n",
    "        def dfs(root):\n",
    "            if root is None:\n",
    "                return root\n",
    "            left = dfs(root.left)\n",
    "            right = dfs(root.right)\n",
    "            if root.val in vals:\n",
    "                return root\n",
    "            if left and right:\n",
    "                return root\n",
    "            return left or right\n",
    "\n",
    "        return dfs(root)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', nodes: 'List[TreeNode]') -> 'TreeNode':\n",
    "        parent_mapping = dict()\n",
    "        if len(nodes) == 0:\n",
    "            return None\n",
    "\n",
    "        def dfs(root, parent=None):\n",
    "            nonlocal parent_mapping\n",
    "            if root is None:\n",
    "                return\n",
    "            parent_mapping[root] = parent\n",
    "            dfs(root.left, root)\n",
    "            dfs(root.right, root)\n",
    "\n",
    "        dfs(root)\n",
    "        if len(nodes) == 1:\n",
    "            return nodes[0]\n",
    "\n",
    "        def calc(a, b):\n",
    "            seen = set()\n",
    "            cur = a\n",
    "            while cur:\n",
    "                seen.add(cur)\n",
    "                cur = parent_mapping[cur]\n",
    "            cur = b\n",
    "            while cur:\n",
    "                if cur in seen:\n",
    "                    return cur\n",
    "                cur = parent_mapping[cur]\n",
    "            return None\n",
    "\n",
    "        result = calc(nodes[0], nodes[1])\n",
    "        for i in range(2, len(nodes)):\n",
    "            result = calc(result, nodes[i])\n",
    "        return result\n",
    "\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', nodes: 'List[TreeNode]') -> 'TreeNode':\n",
    "        # needs = set(nodes)\n",
    "        # def dfs(node):\n",
    "        #     if not node:\n",
    "        #         return\n",
    "        #     if node in needs:\n",
    "        #         return node\n",
    "        #     left = dfs(node.left)\n",
    "        #     right = dfs(node.right)\n",
    "        #     if left and right:\n",
    "        #         return node\n",
    "        #     if left:\n",
    "        #         return left \n",
    "        #     if right:\n",
    "        #         return right\n",
    "        #     return\n",
    "        # return dfs(root)\n",
    "\n",
    "\n",
    "\n",
    "        needs = set(nodes)\n",
    "        \n",
    "        def dfs(node):\n",
    "            if not node:\n",
    "                return (None, 0)\n",
    "            left, left_cnt = dfs(node.left)\n",
    "            right, right_cnt = dfs(node.right)\n",
    "            # if left_cnt == len(needs):\n",
    "            #     return (left, left_cnt)\n",
    "            # if right_cnt == len(needs):\n",
    "            #     return (right, right_cnt)\n",
    "            if node in needs:\n",
    "                return (node, 1 + left_cnt + right_cnt)\n",
    "            if left and right:\n",
    "                return (node, left_cnt+right_cnt)\n",
    "            if left:\n",
    "                return (left, left_cnt)\n",
    "            if right:\n",
    "                return (right, right_cnt)\n",
    "            return (None, 0)\n",
    "    \n",
    "        return dfs(root)[0]\n",
    "        \n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', nodes: 'List[TreeNode]') -> 'TreeNode':\n",
    "        dic = set(nodes)\n",
    "        n = len(nodes)\n",
    "        self.ans = None\n",
    "        def dfs(root):\n",
    "            if root is None: return 0\n",
    "            res = int(root in dic)\n",
    "            res += dfs(root.left) + dfs(root.right)\n",
    "            if res == n:\n",
    "                self.ans = root\n",
    "                res += 1\n",
    "            return res\n",
    "        dfs(root)\n",
    "        return self.ans\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', nodes: 'List[TreeNode]') -> 'TreeNode':\n",
    "        needs = set(nodes)\n",
    "        \n",
    "        def dfs(node):\n",
    "            if not node:\n",
    "                return (None, 0)\n",
    "            left, left_cnt = dfs(node.left)\n",
    "            right, right_cnt = dfs(node.right)\n",
    "            if left_cnt == len(needs):\n",
    "                return (left, left_cnt)\n",
    "            if right_cnt == len(needs):\n",
    "                return (right, right_cnt)\n",
    "            if node in needs:\n",
    "                return (node, 1 + left_cnt + right_cnt)\n",
    "            if left and right:\n",
    "                return (node, left_cnt+right_cnt)\n",
    "            if left:\n",
    "                return (left, left_cnt)\n",
    "            if right:\n",
    "                return (right, right_cnt)\n",
    "            return (None, 0)\n",
    "    \n",
    "        return dfs(root)[0]\n",
    "        \n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', nodes: 'List[TreeNode]') -> 'TreeNode':\n",
    "        needs = set(nodes)\n",
    "        \n",
    "        def dfs(node):\n",
    "            if not node:\n",
    "                return (None, 0)\n",
    "            left, left_cnt = dfs(node.left)\n",
    "            right, right_cnt = dfs(node.right)\n",
    "            if left_cnt == len(needs):\n",
    "                return (left, left_cnt)\n",
    "            if right_cnt == len(needs):\n",
    "                return (right, right_cnt)\n",
    "            if node in needs:\n",
    "                return (node, 1 + left_cnt + right_cnt)\n",
    "            if left and right:\n",
    "                return (node, left_cnt+right_cnt)\n",
    "            if left:\n",
    "                return (left, left_cnt)\n",
    "            if right:\n",
    "                return (right, right_cnt)\n",
    "            return (None, 0)\n",
    "    \n",
    "        return dfs(root)[0]\n",
    "        \n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', nodes: 'List[TreeNode]') -> 'TreeNode':\n",
    "        needs = set(nodes)\n",
    "        \n",
    "        def dfs(node):\n",
    "            if not node:\n",
    "                return (None, 0)\n",
    "            left, left_cnt = dfs(node.left)\n",
    "            right, right_cnt = dfs(node.right)\n",
    "            if left_cnt == len(needs):\n",
    "                return (left, left_cnt)\n",
    "            if right_cnt == len(needs):\n",
    "                return (right, right_cnt)\n",
    "            if node in needs:\n",
    "                return (node, 1 + left_cnt + right_cnt)\n",
    "            if left and right:\n",
    "                return (node, left_cnt+right_cnt)\n",
    "            if left:\n",
    "                return (left, left_cnt)\n",
    "            if right:\n",
    "                return (right, right_cnt)\n",
    "            return (None, 0)\n",
    "    \n",
    "        return dfs(root)[0]\n",
    "        \n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', nodes: 'List[TreeNode]') -> 'TreeNode':\n",
    "        needs = set(nodes)\n",
    "        \n",
    "        def dfs(node):\n",
    "            if not node:\n",
    "                return (None, 0)\n",
    "            left, left_cnt = dfs(node.left)\n",
    "            right, right_cnt = dfs(node.right)\n",
    "            if left_cnt == len(needs):\n",
    "                return (left, left_cnt)\n",
    "            if right_cnt == len(needs):\n",
    "                return (right, right_cnt)\n",
    "            if node in needs:\n",
    "                return (node, 1 + left_cnt + right_cnt)\n",
    "            if left and right:\n",
    "                return (node, left_cnt+right_cnt)\n",
    "            if left:\n",
    "                return (left, left_cnt)\n",
    "            if right:\n",
    "                return (right, right_cnt)\n",
    "            return (None, 0)\n",
    "    \n",
    "        return dfs(root)[0]\n",
    "        \n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', nodes: 'List[TreeNode]') -> 'TreeNode':\n",
    "        needs = set(nodes)\n",
    "        \n",
    "        def dfs(node):\n",
    "            if not node:\n",
    "                return (None, 0)\n",
    "            left, left_cnt = dfs(node.left)\n",
    "            right, right_cnt = dfs(node.right)\n",
    "            if left_cnt == len(needs):\n",
    "                return (left, left_cnt)\n",
    "            if right_cnt == len(needs):\n",
    "                return (right, right_cnt)\n",
    "            if node in needs:\n",
    "                return (node, 1 + left_cnt + right_cnt)\n",
    "            if left and right:\n",
    "                return (node, left_cnt+right_cnt)\n",
    "            if left:\n",
    "                return (left, left_cnt)\n",
    "            if right:\n",
    "                return (right, right_cnt)\n",
    "            return (None, 0)\n",
    "    \n",
    "        return dfs(root)[0]\n",
    "        \n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', nodes: 'List[TreeNode]') -> 'TreeNode':\n",
    "        needs = set(nodes)\n",
    "        \n",
    "        def dfs(node):\n",
    "            if not node:\n",
    "                return (None, 0)\n",
    "            left, left_cnt = dfs(node.left)\n",
    "            right, right_cnt = dfs(node.right)\n",
    "            if left_cnt == len(needs):\n",
    "                return (left, left_cnt)\n",
    "            if right_cnt == len(needs):\n",
    "                return (right, right_cnt)\n",
    "            if node in needs:\n",
    "                return (node, 1 + left_cnt + right_cnt)\n",
    "            if left and right:\n",
    "                return (node, left_cnt+right_cnt)\n",
    "            if left:\n",
    "                return (left, left_cnt)\n",
    "            if right:\n",
    "                return (right, right_cnt)\n",
    "            return (None, 0)\n",
    "    \n",
    "        return dfs(root)[0]\n",
    "        \n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', nodes: 'List[TreeNode]') -> 'TreeNode':\n",
    "        needs = set(nodes)\n",
    "        \n",
    "        def dfs(node):\n",
    "            if not node:\n",
    "                return (None, 0)\n",
    "            left, left_cnt = dfs(node.left)\n",
    "            right, right_cnt = dfs(node.right)\n",
    "            if left_cnt == len(needs):\n",
    "                return (left, left_cnt)\n",
    "            if right_cnt == len(needs):\n",
    "                return (right, right_cnt)\n",
    "            if node in needs:\n",
    "                return (node, 1 + left_cnt + right_cnt)\n",
    "            if left and right:\n",
    "                return (node, left_cnt+right_cnt)\n",
    "            if left:\n",
    "                return (left, left_cnt)\n",
    "            if right:\n",
    "                return (right, right_cnt)\n",
    "            return (None, 0)\n",
    "    \n",
    "        return dfs(root)[0]\n",
    "        \n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', nodes: 'List[TreeNode]') -> 'TreeNode':\n",
    "        visited = dict()\n",
    "        nodes = set(nodes)\n",
    "        ans = None\n",
    "        def dfs(node):\n",
    "            nonlocal ans\n",
    "            if not node:\n",
    "                return set()\n",
    "            \n",
    "            l_contains = dfs(node.left)\n",
    "            r_contains = dfs(node.right)\n",
    "            v = set()\n",
    "            if node in nodes:\n",
    "                v.add(node)\n",
    "            v = v.union(l_contains)\n",
    "            v = v.union(r_contains)\n",
    "            if len(v) == len(nodes) and not ans:\n",
    "                ans = node\n",
    "            return v\n",
    "\n",
    "        dfs(root)\n",
    "        return ans\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', nodes: 'List[TreeNode]') -> 'TreeNode':\n",
    "        nodes=set(nodes)\n",
    "        result_node=None\n",
    "        def method(node):\n",
    "            result=set([])\n",
    "            nonlocal nodes\n",
    "            nonlocal result_node\n",
    "            if node==None:\n",
    "                return result\n",
    "            else:\n",
    "                if node in nodes:\n",
    "                    result=set([node])\n",
    "                result=result.union(method(node.left))\n",
    "                result=result.union(method(node.right))\n",
    "\n",
    "                if result==nodes:\n",
    "                    if result_node==None:\n",
    "                        result_node=node\n",
    "                return result\n",
    "        method(root)\n",
    "\n",
    "        return result_node\n",
    "\n",
    "\n",
    "                \n",
    "\n",
    "\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: 'TreeNode', nodes: 'List[TreeNode]') -> 'TreeNode':\n",
    "        visited = dict()\n",
    "        nodes = set(nodes)\n",
    "        ans = None\n",
    "        def dfs(node):\n",
    "            nonlocal ans\n",
    "            if not node:\n",
    "                return set()\n",
    "            \n",
    "            l_contains = dfs(node.left)\n",
    "            r_contains = dfs(node.right)\n",
    "            v = set()\n",
    "            if node in nodes:\n",
    "                v.add(node)\n",
    "            v = v.union(l_contains)\n",
    "            v = v.union(r_contains)\n",
    "            if len(v) == len(nodes) and not ans:\n",
    "                ans = node\n",
    "            return v\n",
    "\n",
    "        dfs(root)\n",
    "        return ans\n"
   ]
  }
 ],
 "metadata": {},
 "nbformat": 4,
 "nbformat_minor": 2
}
